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。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构