NBearV3 Step by Step教程——ORM篇

版本

1.7 [2006-1-16]

简介

遵照学科演示如何根据NBearV3的ORM模块出一个Web应用程序的皆经过。本学科演示的实业关系包括:继承、1对准1提到、1对几近干,多针对性大多涉及。同时,本学科还现身说法如何规划实体性为nullable类型或称项目。

流淌:所谓nullable类型主要是针对之类型而言的,.Net2.0号拥有的值类型支持nullable,设为nullable的值类型,允许是null的,这样,就可以投数据库中之null;而可项目因是特性是一个复合类型,但是,保存到数据库的下,整个复合类型序列化后保存也一个数据表的字段的值。

目标

经以课程,读者应会支配使用NBearV3的ORM模块进行应用程序设计之主导历程,以及支出进程遭到,NBearV3提供的有关工具的动方法。

代码

遵学科演示创建的兼具工程以及代码,包含于得从sf.net下载的NBearV3最新源码zip包中之tutorials\ORM_Tutorial目录中。因此,在用仍学科的长河中一经发生任何疑窦,可以一直参考这些代码。

时间

<45分钟。

正文

Step 1 下载NBearV3最新版本

1.1访问http://sf.net/projects/nbear,下载NBearV3的时版本及地头目录。

1.2
将下载的zip文件解压至C:\,您将张,加压后底NBearV3目录中连:dist、doc、cases、src等目录。其中,在本教程中拿会晤使的凡dist目录,该目录下涵有release编译版本的dll和exe。

Step 2 创建应用程序解决方案

2.1 打开VS2005开条件,新建一个空的解决方案sln。

2.2
向sln中上加少单新建的C#类库工程,两独类库工程的称分别吗EntityDesigns和Entities,删除IDE自动创建的Class1.cs文书。

2.3 向sln中新构筑一个称呼website的ASP.NET
Web应用程序,为website添加一个Web.config文件。

Step 3 设计实体和涉

3.1
在2.2开立的EntityDesigns工程被,新建一个叫吧ClassDiagram.cd的类图文件。注:如果您的IDE不支持类图设计,或者你还习惯写代码,您吗得参照下的步骤直接创造代码。

3.2啊EntityDesigns工程填补加至dist目录下之NBear.Common.Design.dll的援。因为下面的各个一个企划实体接口必须连续自NBear.Common.Design.Entity这个接口。在Entities工程被开创一个称也UserName的struct包含FirstName和LastName两单string类型的Field。同时以Entities工程被开创一个称作吧UserStatus的枚举类型,包含两个枚举选项:Availale和Deleted。注:这有限只项目将用来末端的规划实体的规划。之所以这点儿个类型定义在Entities工程被只要不是EntityDesigns工程中凡,最终,所有变化的实体将放在Entities工程,且Entities工程最后对EntityDesigns工程是不曾依赖关系的。

3.3
双击ClassDiagram.cd打开设计界面,您现在就算好计划实体了。注意,所有的计划性实体必须是接口。为了用3.2开立的类别,需要为Entit一Designs工程引用Entities工程。

3.4
向类图中上加一个User接口,继承自NBear.Common.Design.Entity。添加属性ID,Name,Status和Birthday。类型分别吗Guid、UserName、UserStatus和DateTime?。注意,这里的Name和Status的路也3.2创的自定义符合项目UserName和枚举类型UserStatus。而Birthday属性的档次也一个Nullable类型的DateTime?。注意DateTime后面的问号,表示这类型实际是一个Nullable<DateTime>,也就是说,Birthday类型如果无赋初始值的说话,它的值为null。

3.5
向类图中再次添加一个LocalUser接口,继承自NBear.Common.Design.Entity。添加属性LoginName和Password。类型且也string。

3.6 从工具栏添加继承线条,让LocalUser继承User。

3.7
向类图中补充加一个UserProfile接口,继承自NBear.Common.Design.Entity。添加属性ID,UserID和ProfileContent。类型分别吗Guid,Guid和string。注:这里的ProfileContent仅仅象征型的意味profile数据,用于演示1对准1事关,实际的类型遭到或许会见出再多属性。

3.8
从工具栏添加关系线条,让User包含一个称为Profile的UserProfile类型的性能。这样我们便1对1关联了User和UserProfile实体。注:如果操作图形设计界面觉得累,也足以切换到源代码界面,直接编码。

3.9
向类图中上加一个LocalUserPhone接口,继承自NBear.Common.Design.Entity。添加属性ID,UserID,Description,Number。类型分别吗Guid,Guid,string和string。

3.10
打工具栏添加关系线条,让LocalUser包含一个称为Phones的花色也LocalUserPhone[]的数组类型的性质。这样咱们就1对准几近干了LocalUser和UserPhone。

3.11
向类图上加一个Group接口,继承自NBear.Common.Design.Entity。添加属性ID,Name。类型分别吗Guid和string。

3.12
从工具栏添加关系线条,让User包含一个称Groups的类型也Group[]的数组类型的性。注意,这里我们如果贯彻的是基本上对准几近干,所以下面我们还要建一个UserGroup关联实体来连接这个差不多对准几近干。

3.13
向类图上加一个UserGroup接口,继承自NBear.Common.Design.Entity。添加属性UserID和GroupID。类型且是Guid。

筹完毕的实业关系图,应该接近下面这样:

图片 1

Step 4 设置规划实体元数据

4.1
切换到源代码视图。首先,我们若呢除去关乎实体UserGroup之外(对于涉嫌实体,凡是标记为RelationKey的属性,会给机关认为是复合主键)的拥有规划实体的主键设置PrimaryKey这个Attribute,可以呢多主键实体的每个主键添加该属性。如果无科学安装主键,代码生成工具将未能够科学生成数据库创建脚本。例如,对于User实体的ID属性,设置后底代码象下面这样:

图片 2        [PrimaryKey]
图片 3        Guid ID
图片 4图片 5        图片 6{
图片 7            get;
图片 8            set;
图片 9        }

流动:大家也许来问号,为什么这里主键ID能无可知是int,并且是自从增长的单纯读属性为?答案是意好的,完全可装有ID属性为底这样,无需额外安装,它以照到一个起增长就念之int类型的数据库字段:

图片 10        [PrimaryKey]
图片 11        int ID
图片 12图片 13        图片 14{
图片 15            get;
图片 16        }

4.2
在后面的步骤生成实体对应之数据库创建脚本时,对于数值类,nullable类型和枚举类型,NBear能够自行将她们本着许到数据库的相应品种,但是,针对string类型,一般需要指定其映射到数据库时之切实品种以及长。当然,也可以不点名,如果未指定,则string类型默认为射为nvarchar(127)。例如,对于UserProfile的ProfileContent属性,我们抬高下面的Attribute,设置其映射到数据库的类为ntext:

图片 17        [SqlType(“ntext”)]
图片 18        string ProfileContent
图片 19图片 20        图片 21{
图片 22            get;
图片 23            set;
图片 24        }

并且要,对于LocalUserPhone的Number属性,我们抬高下面的Attribute,设置其映射到数据库的种类为nvarchar(20):

图片 25        [SqlType(“nvarchar(20)”)]
图片 26        string Number
图片 27图片 28        图片 29{
图片 30            get;
图片 31            set;
图片 32        }

4.2
对于User的Name这个UserName类型的复合类型,我们也急需装其SqlType,一般设为ntext,因为,默认情况下复合类型为排化为XML,并保留于对应的数据库字段。另外,复合类型还须以CompoundUnit这个Attribute标记,所以User的Name属性需要为装成下面这样:

图片 33        [CompoundUnit]
图片 34        [SqlType(“ntext”)]
图片 35        UserName Name
图片 36图片 37        图片 38{
图片 39            get;
图片 40            set;
图片 41        }

注:累关系匪需专门设置,NBear可以分辨接口的自继承关系,但是,注意,不要受一个计划实体接口继承超过一个基类接口,否则,NBear将非克识别这种持续关系。换句话说,NBear不支持多绝望继承。之所以产生是界定是为,后面,所有这些计划实体接口会让自动生成为class形式之实业代码,而class是不支持多根继承的。

4.3 对于User和UserProfile的1对1关联,我们用为User接口的Profile属性装下面的Attributes(这些Attribues都含于NBear.Common.Design中,因此,需要小心在代码中using
NBear.Common.Design):

图片 42        [FkQuery(“UserID”, Contained = true, LazyLoad = false)]
图片 43        UserProfile Profile
图片 44图片 45        图片 46{
图片 47            get;
图片 48            set;
图片 49        }

其中,FkQuery代表是特性是一个1对准1外键关联,参数UserID代表,在UserProfile实体中,UserID为对应之外键。LazyLoad=false容易掌握,表示这个特性不是了解看才载入数据的,而是,在实例化User对象的时刻,就活动载入Profile属性的数据。当然,如果用,也堪以LazyLoad设为true。另外,可以像下这样设置UserProfile的UserID属性为外键,则变的数据库脚本将涵盖外键引用完整性检测:

图片 50        [FriendKey(typeof(User))]
图片 51        Guid UserID
图片 52图片 53        图片 54{
图片 55            get;
图片 56            set;
图片 57        }

4.4 对于LocalUser和LocalUserPhone的1针对几近干,我们要呢LocalUser接口的Phones属性安下对的Attributes

图片 58        [FkQuery(“UserID”, Contained=true, LazyLoad=true)]
图片 59        LocalUserPhone[] Phones
图片 60图片 61        图片 62{
图片 63            get;
图片 64            set;
图片 65        }

这里LocalUser和LocalUserPhones是1针对多外键关联。Contained=true表示Phones跟随LocalUser级联更新。

4.5 对于User和Group的差不多对几近干,我们为User.Groups属性装下面的Attributes

图片 66        [ManyToManyQuery(typeof(UserGroup), OrderBy=”{Name} DESC”, LazyLoad=true)]
图片 67        Group[] Groups
图片 68图片 69        图片 70{
图片 71            get;
图片 72            set;
图片 73        }

咱得以看来,和前面的1对准1以及1对大多涉及相比,多对多关系的重要区别是必须安装ManyToManyQuery的构造函数参数,指定关联实体为UserGroup。这里的OrderBy并无是必的,如果不指定,则载入的Group按默认规则排序。

4.6
另外,还需装UserGroup这个关系实体的性质如何和User和Group的习性进行关联。我们需要针对UserGroup这个实体关联接口及她的性能设定下面的Attributes:

图片 74    [Relation]
图片 75    public interface UserGroup : NBear.Common.Design.Entity
图片 76图片 77    图片 78{
图片 79        [RelationKey(typeof(User))]
图片 80        Guid UserID
图片 81图片 82        图片 83{
图片 84            get;
图片 85            set;
图片 86        }
图片 87
图片 88        [RelationKey(typeof(Group))]
图片 89        Guid GroupID
图片 90图片 91        图片 92{
图片 93            get;
图片 94            set;
图片 95        }
图片 96    }

 注意,首先,干实体必须以Relation这个Attribute修饰。其次,每一个涉属性的用于关联的特性,必须采取RelationKey这个Attribute修饰。RelationKey的唯一参数指定这个特性关联到哪一个实体。比如说,这里,UserGroup的UserID属性关联到User实体;而GroupID属性则涉及到Group实体。

4.7
对于LocalUser的Password,我们可长NotNull和SerializationIgnore这半独Attribute,显式地安装其针对性许字段为非空,并且,保证其无见面被含有在默认的XML序列化中。设置到规划实体的SerializationIgnore,会以末生成的实体中之所以XmlIngore标识。

图片 97        [SqlType(“nvarchar(50)”)]
图片 98        [NotNull]
图片 99        [SerializationIgnore]
图片 100        string Password
图片 101图片 102        图片 103{
图片 104            get;
图片 105            set;
图片 106        }

Step 5 从实体设计代码生成实体代码、实体配置文件以及数据库生成脚本

5.1 至这,所有的实业的计划虽截止了。编译EntityDesigns工程。

5.2
运行dist目录中的NBear.Tools.EntityDesignToEntity.exe工具,载入EntityDesigns工程编译生成的EntityDesigns.dll。

5.3 点击Generate
Entities按钮,将扭转的代码保存及Entities工程被的一个叫作Entities.cs的初代码文件。并也Entities工程填补加到dist\NBear.Common.dll的引用。

5.4 点击Generate
Configuration按钮,将转移的代码保存至website工程下的名为EntityConfig.xml的新文件中。

5.5 点击Generate DB
Script按钮,将扭转的代码保存及website工程下的名叫吧db.sql的新文件,可以以有新建的SQL
Server数据库被履行这些本子,创建对应于所有实体的数据库脚本。

Step 6 使用实体和NBear.Data.Gateway访问数据库

6.1
现在我们就是足以利用前生成的实业了。我们先使吃website工程引用Entities工程,以及dist/NBear.Data.dll。

6.2 我们尚需安装website的Web.config文件,添加一个entityConfig
section以富含EntityConfig.xml这个实体配置文件,并安装数据库连接字串。下面是设置完毕的Web.config,注意,粗体的有的都是我们添加的代码(注意,这里的connectionstring连接受SQL
Server数据库的tempdb数据库,我们要针对tempdb数据库执行5.5不行成的数据库创建脚本,另外为只顾修改数据库登录密码。):

图片 107<?xml version=”1.0″?>
图片 108<configuration>
图片 109 <configSections>
图片 110    **<section name=”entityConfig” type=”NBear.Common.EntityConfigurationSection, NBear.Common” /> 图片 111 **</configSections>
图片 112 **<entityConfig> 图片 113    **<includes>
图片 114      **<add key=”Sample Entity Config” value=”~/EntityConfig.xml” /> 图片 115    **</includes>
图片 116 **</entityConfig>
图片 117 <appSettings/>
图片 118 
<connectionStrings> 图片 119    **<add name=”DbName” connectionString=”Server=(local);Database=tempdb;Uid=sa;Pwd=sa” providerName=”NBear.Data.SqlServer.SqlDbProvider”/>
图片 120 **</connectionStrings>**
图片 121 <system.web>
图片 122        <compilation debug=”false” />
图片 123        <authentication mode=”Windows” /
图片 124    </system.web>
图片 125</configuration>

6.3
好了,现在,我们虽得随意的访问数据库了。将下的代码添加至website工程的Default.aspx.cs文件(您也足以直接打开tutorials\
ORM_Tutorial\website目录下之Default.aspx.cs,从那里复制代码)。这些代码演示了一个杀典型的缔造和级联更新有千丝万缕关系之实业的经过,并陪同有详尽分解。关于Gateway支持之又多方式的牵线,可以参见doc目录下的SDK类库文档。

图片 126using System;
图片 127using System.Data;
图片 128using System.Configuration;
图片 129using System.Web;
图片 130using System.Web.Security;
图片 131using System.Web.UI;
图片 132using System.Web.UI.WebControls;
图片 133using System.Web.UI.WebControls.WebParts;
图片 134using System.Web.UI.HtmlControls;
图片 135
图片 136using Entities;
图片 137using NBear.Common;
图片 138using NBear.Data;
图片 139
图片 140public partial class _Default : System.Web.UI.Page 
图片 141图片 142图片 143{
图片 144    protected void Page_Load(object sender, EventArgs e)
图片 145图片 146    图片 147{
图片 148        //init a Gateway, the param “tempdb” is the connectionstring name set in Web.config
图片 149        Gateway gateway = new Gateway(“tempdb”);    //youcan also use gateway = Gateway.Default, which maps to the last connectionstring in Web.config
图片 150
图片 151图片 152        create & save a LocalUser#region create & save a LocalUser
图片 153
图片 154        WriteLine(“Create a new local user and set property values.”);
图片 155        LocalUser newLocalUser = new LocalUser();
图片 156        newLocalUser.ID = Guid.NewGuid();
图片 157        newLocalUser.Password = “12345”;
图片 158        //by default, newUser.Birthday equals null, because it is DateTime? type, which means when saved in database, its value is dbnull.
图片 159        //newUser.Birthday = null
图片 160
图片 161        //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
图片 162        //you should not assign value directly to the compoundunit property’s property like “newUser.Name.FirstName = XXX”, 
图片 163        //or, a compile-time warning will be thrown
图片 164        WriteLine(“Create & set the user name.”);
图片 165        UserName newUserName = new UserName();
图片 166        newUserName.FirstName = “teddy”;
图片 167        newUserName.LastName = “ma”;
图片 168        newLocalUser.Name = newUserName; //must create the compoundunit type first, and then assign it to the property
图片 169
图片 170        newLocalUser.Status = UserStatus.Available;
图片 171
图片 172        //create and assign the 1 to 1 related Profile property
图片 173        UserProfile newUserProfile = new UserProfile();
图片 174        newUserProfile.ID = Guid.NewGuid(); //create it first
图片 175        newUserProfile.UserID = newLocalUser.ID;
图片 176        newUserProfile.ProfileContent = “some sample content”;
图片 177        newLocalUser.Profile = newUserProfile;   //assign it to the property
图片 178
图片 179        //create two phones and assign the 1 to many related Phones property
图片 180        WriteLine(“Create & set the local user phones”);
图片 181        LocalUserPhone[] newPhones = new LocalUserPhone[2];
图片 182        newPhones[0] = new LocalUserPhone();    //create first phone
图片 183        newPhones[0].Description = “home”;
图片 184        newPhones[0].ID = Guid.NewGuid();
图片 185        newPhones[0].UserID = newLocalUser.ID;
图片 186        newPhones[0].Number = “111”;
图片 187        newPhones[1] = new LocalUserPhone();    //create second phone
图片 188        newPhones[1].Description = “work”;
图片 189        newPhones[1].ID = Guid.NewGuid();
图片 190        newPhones[1].UserID = newLocalUser.ID;
图片 191        newPhones[1].Number = “222”;
图片 192        LocalUserPhoneArrayList newPhoneList = new LocalUserPhoneArrayList();
图片 193        newPhoneList.AddRange(newPhones);
图片 194        newLocalUser.Phones = newPhoneList;    //assign it to the property
图片 195
图片 196        //create a group and assign it to the Groups property
图片 197        WriteLine(“Create & set the user groups.”);
图片 198        Group newGroup = new Group();
图片 199        newGroup.ID = Guid.NewGuid();
图片 200        newGroup.Name = “new group”;
图片 201        GroupArrayList groupList = new GroupArrayList();
图片 202        groupList.Add(newGroup);
图片 203        newLocalUser.Groups = groupList; //another way to add a item to array property
图片 204
图片 205        //save newLocalUser
图片 206        WriteLine(“Save the new local user.”);
图片 207        gateway.Save<LocalUser>(newLocalUser);  //do you know what is happening when saving the new local user?
图片 208
图片 209        #endregion
图片 210
图片 211图片 212        Check saving result#region Check saving result
图片 213
图片 214        WriteLine(“”);
图片 215        WriteLine(“After we saved the local user.”);
图片 216
图片 217        //let find the saved local user by id first
图片 218        LocalUser theSavedLocalUser = gateway.Find<LocalUser>(newLocalUser.ID);
图片 219        if (theSavedLocalUser != null) WriteLine(“We found the saved local user itself.”);
图片 220
图片 221        //a local user is also a user, right? then could we find the saved local user as a user?
图片 222        User theSavedLocalUserAsUser = gateway.Find<User>(newLocalUser.ID);
图片 223        if (theSavedLocalUser != null) WriteLine(“We found the saved local user itself as a user.”);
图片 224
图片 225        //was the 1 to 1 related user profile saved on the new local user’s saving?
图片 226        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.”);
图片 227
图片 228        //were the 1 to many related local user phones saved on the new local user’s saving?
图片 229        if (theSavedLocalUser.Phones != null && theSavedLocalUser.Phones[0].ID == newLocalUser.Phones[0].ID && theSavedLocalUser.Phones[1].ID == newLocalUser.Phones[1].ID)
图片 230            WriteLine(“We found the 1 to many related local user phones of the saved local user were also saved.”);
图片 231
图片 232        //were the many to many related user group and the usergroup relation entity saved on the new local user’s saving?
图片 233        if (theSavedLocalUser.Groups != null && theSavedLocalUser.Groups.Count > 0 && theSavedLocalUser.Groups[0].ID == newLocalUser.Groups[0].ID)
图片 234            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.
图片 235        else
图片 236            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.”);
图片 237
图片 238        //save an uncontained property’s value
图片 239        WriteLine(“To save an uncontained property value, such as user’s Groups, you have to manually do this.”);
图片 240        WriteLine(“Firstly, you should save the group it self.”);
图片 241        gateway.Save<Group>(newGroup);
图片 242        WriteLine(“Furthermore, you have to create & save a usergroup relation entity manually. Let’s do it.”);
图片 243        UserGroup newUserGroup = new UserGroup();   //create the new usergroup relation entity instance
图片 244        newUserGroup.UserID = theSavedLocalUser.ID;
图片 245        newUserGroup.GroupID = newGroup.ID;
图片 246        gateway.Save<UserGroup>(newUserGroup);  //do the saving
图片 247        WriteLine(“Let’s find the saved local user again. Was the group saved this time?”);
图片 248        theSavedLocalUser = gateway.Find<LocalUser>(newLocalUser.ID);
图片 249        if (theSavedLocalUser.Groups != null && theSavedLocalUser.Groups.Count > 0 && theSavedLocalUser.Groups[0].ID == newLocalUser.Groups[0].ID)
图片 250            WriteLine(“Yes, conguratulation! This time, we found the many to many related local user group of the saved local user was finally saved.”);
图片 251        
图片 252        //to see the saved user name details
图片 253        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:”);
图片 254        WriteLine(SerializationManager.Serialize(theSavedLocalUser.Name));
图片 255        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!!”);
图片 256        WriteLine(“What youshould do is easily register a custom serialize/deserialize delegate method pair.”);
图片 257        SerializationManager.RegisterSerializeHandler(typeof(UserName), new SerializationManager.TypeSerializeHandler(CustomSerializeUserName), new SerializationManager.TypeDeserializeHandler(CustomDeserializeUserName));
图片 258        WriteLine(“Let’s save the user name again.”);
图片 259        theSavedLocalUser.Name = newUserName;
图片 260        gateway.Save<LocalUser>(theSavedLocalUser);
图片 261        WriteLine(“What does the details of the user name now become? It becomes:”);
图片 262        WriteLine(SerializationManager.Serialize(theSavedLocalUser.Name));
图片 263        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().”);
图片 264        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.”);
图片 265        WriteLine(“See you later!”);
图片 266        WriteLine(“Warm regards,”);
图片 267        WriteLine(“Teddy ” + DateTime.Now.ToShortDateString());
图片 268        SerializationManager.UnregisterSerializeHandler(typeof(UserName));
图片 269
图片 270        #endregion
图片 271    }
图片 272
图片 273    private void WriteLine(string str)
图片 274图片 275    图片 276{
图片 277        Response.Write(Server.HtmlEncode(str) + “<br /><br />”);
图片 278    }
图片 279
图片 280    private string CustomSerializeUserName(object name)
图片 281图片 282    图片 283{
图片 284        UserName userName = (UserName)name;
图片 285        return userName.FirstName + “,” + userName.LastName;
图片 286    }
图片 287
图片 288    private object CustomDeserializeUserName(string data)
图片 289图片 290    图片 291{
图片 292        string[] splittedData = data.Split(‘,’);
图片 293        UserName userName = new UserName();
图片 294        userName.FirstName = splittedData[0];
图片 295        userName.LastName = splittedData[1];
图片 296        return userName;
图片 297    }
图片 298}

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"&gt;
<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数据库。

图片 299<connectionStrings>
图片 300   <add name=”TestAccessDb” connectionString=”Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Teddy\NBear\skeleton\Simple\website\App_Data\TestAccessDb.mdb” providerName=”NBear.Data.MsAccess.AccessDbProvider”/>
图片 301   <add name=”Northwind” connectionString=”Server=(local);Database=Northwind;Uid=sa;Pwd=sa” providerName=”NBear.Data.SqlServer.SqlDbProvider”/>
图片 302   <add name=”Northwind2″ connectionString=”Server=(local);Database=Northwind;Uid=sa;Pwd=sa” providerName=”NBear.Data.SqlServer9.SqlDbProvider9″/>
图片 303   <add name=”MySql” connectionString=”Dsn=mysqltest;database=test;option=3;server=localhost;uid=root;password=sa” providerName=”NBear.Data.MySql.MySqlDbProvider”/>
图片 304   <add name=”Oracle” connectionString=”Data Source=localhost;User ID=system;Password=sa;Unicode=True” providerName=”NBear.Data.Oracle.OracleDbProvider”/>
图片 305</connectionStrings>

2 关于Gateway的初始化和连接多数据库

 

除却采取Gateway.Default之外,还足以下两种植方法实例化Gateway:

1)使用安排文件被的ConnectionString的name属性对应之称号来初始化Gateway。例如,

图片 306public static Gateway Northwind = new Gateway(“Northwind”);
图片 307public static Gateway TestAccessDb = new Gateway(“TestAccessDb”);

咱们得像这么实例化多只Gateway对许不同的ConnectionString。

2)如果您不将ConnectionString定义为应用程序的配备文件中,那么,就得一直提供ConnectionString来初始化了。下面是几只卓越的初始化示例:

图片 308Gateway TestDbAccess = new Gateway(DatabaseType.MsAccess, @”C:\Teddy\NBear\skeleton\Simple\website\App_Data\TestAccessDb.mdb”);
图片 309Gateway Northwind = new Gateway(DatabaseType.SqlServer, @”Server=(local);Database=Northwind;Uid=sa;Pwd=sa”);
图片 310Gateway Northwind2 = new Gateway(DatabaseType.SqlServer9, @”Server=(local)\SQLEXPRESS;Database=Northwind;Uid=sa;Pwd=sa”);
图片 311Gateway.Default = new Gateway(DatabaseType.MySql, “Dsn=mysqltest;database=test;option=3;server=localhost;uid=root;password=sa”);
图片 312Gateway.Default = new Gateway(DatabaseType.Oracle, “Data Source=localhost;User ID=system;Password=sa;Unicode=True”);

顾上述的代码用了Gateway构造函数的其他一个重载版本,接受一个DatabaseType参数与一个ConnectionString。这五行示例分别实例化了针对性应于MSAccess、MS
SQL Server 2000、MS SQL Server 2005、MySql和Oracle的数据库的Gateway。

//本文结束。

相关文章