using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using Entities; using NBear.Common; using NBear.Data; public partial class _Default : System.Web.UI.Page { protectedvoid Page_Load(object sender, EventArgs e) { //init a Gateway, the param "tempdb" is the connectionstring name set in Web.config Gateway gateway =new Gateway("tempdb"); //youcan also use gateway = Gateway.Default, which maps to the last connectionstring in Web.config create & save a LocalUser#region create & save a LocalUser WriteLine("Create a new local user and set property values."); LocalUser newLocalUser =new LocalUser(); newLocalUser.ID = Guid.NewGuid(); newLocalUser.Password ="12345"; //by default, newUser.Birthday equals null, because it is DateTime? type, which means when saved in database, its value is dbnull. //newUser.Birthday = null //if you want to set a compoundunit property like User.Name, you must create the compoundunit type first, and then assign it to the property //you should not assign value directly to the compoundunit property's property like "newUser.Name.FirstName = XXX", //or, a compile-time warning will be thrown WriteLine("Create & set the user name."); UserName newUserName =new UserName(); newUserName.FirstName ="teddy"; newUserName.LastName ="ma"; newLocalUser.Name = newUserName; //must create the compoundunit type first, and then assign it to the property newLocalUser.Status = UserStatus.Available; //create and assign the 1 to 1 related Profile property UserProfile newUserProfile =new UserProfile(); newUserProfile.ID = Guid.NewGuid(); //create it first newUserProfile.UserID = newLocalUser.ID; newUserProfile.ProfileContent ="some sample content"; newLocalUser.Profile = newUserProfile; //assign it to the property //create two phones and assign the 1 to many related Phones property WriteLine("Create & set the local user phones"); LocalUserPhone[] newPhones =new LocalUserPhone[2]; newPhones[0] =new LocalUserPhone(); //create first phone newPhones[0].Description ="home"; newPhones[0].ID = Guid.NewGuid(); newPhones[0].UserID = newLocalUser.ID; newPhones[0].Number ="111"; newPhones[1] =new LocalUserPhone(); //create second phone newPhones[1].Description ="work"; newPhones[1].ID = Guid.NewGuid(); newPhones[1].UserID = newLocalUser.ID; newPhones[1].Number ="222"; LocalUserPhoneArrayList newPhoneList =new LocalUserPhoneArrayList(); newPhoneList.AddRange(newPhones); newLocalUser.Phones = newPhoneList; //assign it to the property //create a group and assign it to the Groups property WriteLine("Create & set the user groups."); Group newGroup =new Group(); newGroup.ID = Guid.NewGuid(); newGroup.Name ="new group"; GroupArrayList groupList =new GroupArrayList(); groupList.Add(newGroup); newLocalUser.Groups = groupList; //another way to add a item to array property //save newLocalUser WriteLine("Save the new local user."); gateway.Save<LocalUser>(newLocalUser); //do you know what is happening when saving the new local user? #endregion Check saving result#region Check saving result WriteLine(""); WriteLine("After we saved the local user."); //let find the saved local user by id first LocalUser theSavedLocalUser = gateway.Find<LocalUser>(newLocalUser.ID); if (theSavedLocalUser !=null) WriteLine("We found the saved local user itself."); //a local user is also a user, right? then could we find the saved local user as a user? User theSavedLocalUserAsUser = gateway.Find<User>(newLocalUser.ID); if (theSavedLocalUser !=null) WriteLine("We found the saved local user itself as a user."); //was the 1 to 1 related user profile saved on the new local user's saving? if (theSavedLocalUser.Profile !=null&& theSavedLocalUser.Profile.ID == newLocalUser.Profile.ID) WriteLine("We found the 1 to 1 related user profile of the saved local user was also saved."); //were the 1 to many related local user phones saved on the new local user's saving? if (theSavedLocalUser.Phones !=null&& theSavedLocalUser.Phones[0].ID == newLocalUser.Phones[0].ID && theSavedLocalUser.Phones[1].ID == newLocalUser.Phones[1].ID) WriteLine("We found the 1 to many related local user phones of the saved local user were also saved."); //were the many to many related user group and the usergroup relation entity saved on the new local user's saving? if (theSavedLocalUser.Groups !=null&& theSavedLocalUser.Groups.Count >0&& theSavedLocalUser.Groups[0].ID == newLocalUser.Groups[0].ID) WriteLine("We found the many to many related local user group of the saved local user was also saved."); //is the line really executed?? it should not. else WriteLine("Oh! many to many related local user group of the saved local user was NOT saved!! Do you know why? - It is NOT because it is many to many related while profile and phones are 1 to 1 or 1 to many. It is not because you are not Teddy, either. :) It IS because in the entity design of User, the Groups property is NOT marked with the [Contained] attribute."); //save an uncontained property's value WriteLine("To save an uncontained property value, such as user's Groups, you have to manually do this."); WriteLine("Firstly, you should save the group it self."); gateway.Save<Group>(newGroup); WriteLine("Furthermore, you have to create & save a usergroup relation entity manually. Let's do it."); UserGroup newUserGroup =new UserGroup(); //create the new usergroup relation entity instance newUserGroup.UserID = theSavedLocalUser.ID; newUserGroup.GroupID = newGroup.ID; gateway.Save<UserGroup>(newUserGroup); //do the saving WriteLine("Let's find the saved local user again. Was the group saved this time?"); theSavedLocalUser = gateway.Find<LocalUser>(newLocalUser.ID); if (theSavedLocalUser.Groups !=null&& theSavedLocalUser.Groups.Count >0&& theSavedLocalUser.Groups[0].ID == newLocalUser.Groups[0].ID) WriteLine("Yes, conguratulation! This time, we found the many to many related local user group of the saved local user was finally saved."); //to see the saved user name details WriteLine("Do you want to know the saved user name's details, which is a compoundunit property? Ok, show you what you want, in fact, it is serialized as xml by the NBear.Common.SerializationManager class, looks like:"); WriteLine(SerializationManager.Serialize(theSavedLocalUser.Name)); WriteLine("Ok, I heard you considering whether you can save it into some other format because you do not want it to be XML? You do have chance to control this!!"); WriteLine("What youshould do is easily register a custom serialize/deserialize delegate method pair."); SerializationManager.RegisterSerializeHandler(typeof(UserName), new SerializationManager.TypeSerializeHandler(CustomSerializeUserName), new SerializationManager.TypeDeserializeHandler(CustomDeserializeUserName)); WriteLine("Let's save the user name again."); theSavedLocalUser.Name = newUserName; gateway.Save<LocalUser>(theSavedLocalUser); WriteLine("What does the details of the user name now become? It becomes:"); WriteLine(SerializationManager.Serialize(theSavedLocalUser.Name)); WriteLine("Cool!~~ Right? But remember, in real project, you must register the custom serialize/deserialize delegate method pair at application started up. For example, in Application_Start()."); WriteLine("Thank you so much for having completed this tutorial. You can look up the appendixes, for more information about the usage of the Gateway."); WriteLine("See you later!"); WriteLine("Warm regards,"); WriteLine("Teddy "+ DateTime.Now.ToShortDateString()); SerializationManager.UnregisterSerializeHandler(typeof(UserName)); #endregion } privatevoid WriteLine(string str) { Response.Write(Server.HtmlEncode(str) +"<br /><br />"); } privatestring CustomSerializeUserName(object name) { UserName userName = (UserName)name; return userName.FirstName +","+ userName.LastName; } privateobject CustomDeserializeUserName(string data) { string[] splittedData = data.Split(','); UserName userName =new UserName(); userName.FirstName = splittedData[0]; userName.LastName = splittedData[1]; return userName; } }
6.4 运行以上代码,您将得到类似到下面的结果:
Create a new local user and set property values. Create & set the user name. Create & set the local user phones Create & set the user groups. Save the new local user.
After we saved the local user. We found the saved local user itself. We found the saved local user itself as a user. We found the 1 to 1 related user profile of the saved local user was also saved. Oh! many to many related local user group of the saved local user was NOT saved!! Do you know why? - It is NOT because it is many to many related while profile and phones are 1 to 1 or 1 to many. It is not because your are not Teddy, either. :) It IS because in the entity design of User, the Groups property is NOT marked with the [Contained] attribute. To save an uncontained property value, such as user's Groups, you have to manually do this. Firstly, you should save the group it self. Furthermore, you have to create & save a usergroup relation entity manually. Let's do it. Let's find the saved local user again. Was the group saved this time? Yes, conguratulation! This time, we found the many to many related local user group of the saved local user was finally saved. Do you want to know the saved user name's details, which is a compoundunit property? Ok, show you what you want, in fact, it is serialized as xml by the NBear.Common.SerializationManager class, looks like: <?xml version="1.0" encoding="utf-16"?> <UserName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <FirstName>teddy</FirstName> <LastName>ma</LastName> </UserName> Ok, I heard you considering whether you can save it into some other format because you do not want it to be XML? You do have chance to control this!! What youshould do is easily register a custom serialize/deserialize delegate method pair. Let's save the user name again. What does the details of the user name now become? It becomes: teddy,ma Cool!~~ Right? But remember, in real project, you must register the custom serialize/deserialize delegate method pair at application started up. For example, in Application_Start(). Thank you so much for having completed this tutorial. You can look up the appendixes, for more information about the usage of the Gateway. See you later! Warm regards, Teddy 2006-11-3
正文结束。
附录
1 关于ConnectionStrings的设置
这里定义了五个ConnectionString,分别对应MS Access、MS SQL Server、SQL Server 2005、MySql和Oracle数据库。
注意以上的代码使用了Gateway构造函数的另一个重载版本,接受一个DatabaseType参数和一个ConnectionString。这五行示例分别实例化了对应于MSAccess、MS SQL Server 2000、MS SQL Server 2005、MySql和Oracle的数据库的Gateway。