博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Entity Framework技术系列之3:对象-关系映射
阅读量:6539 次
发布时间:2019-06-24

本文共 25138 字,大约阅读时间需要 83 分钟。

前言

Entity Framework技术是通过SSDL(Storage Schema Definition Language)、CSDL(Conceptual Schema Definition Language)和MSL(Mapping Concept and Storage Schema Language)三层映射语言来实现对象-关系映射的。下图展示了Entity Framework对象-关系映射技术架构:

 

1实体数据模型内容结构图

 

E-R模型

本文示例使用的E-R模型如下图所示:

 

2 E-R模型图

对应的DDL语句如下:

1 --创建表 2 CREATE TABLE [Role]( 3     [ID] [uniqueidentifier] NOT NULL, 4     [Name] [nvarchar](40) NOT NULL, 5     [ParentID] [uniqueidentifier] NULL) 6 GO 7  8 CREATE TABLE [User]( 9     [ID] [uniqueidentifier] NOT NULL,10     [Account] [nvarchar](50) NOT NULL,11     [Password] [varchar](50) NOT NULL)12 GO13 14 CREATE TABLE [UserDetail](15     [ID] [uniqueidentifier] NOT NULL,16     [Name] [nvarchar](50) NOT NULL,17     [Sex] [nvarchar](2) NULL,18     [Birthday] [datetime] NULL)19 GO20 21 CREATE TABLE [UserRole](22     [UserID] [uniqueidentifier] NOT NULL,23     [RoleID] [uniqueidentifier] NOT NULL)24 GO25 26 --创建主键27 ALTER TABLE [Role]28 ADD CONSTRAINT [PK_Role]29     PRIMARY KEY CLUSTERED ([ID] ASC);30 GO31 32 ALTER TABLE [User]33 ADD CONSTRAINT [PK_User]34     PRIMARY KEY CLUSTERED ([ID] ASC);35 GO36 37 ALTER TABLE [UserDetail]38 ADD CONSTRAINT [PK_UserDetail]39     PRIMARY KEY CLUSTERED ([ID] ASC);40 GO41 42 ALTER TABLE [UserRole]43 ADD CONSTRAINT [PK_UserRole]44     PRIMARY KEY CLUSTERED ([UserID] ASC, RoleID ASC);45 GO46 47 --创建外键48 ALTER TABLE [Role] WITH CHECK ADD CONSTRAINT [FK_Role_Role] FOREIGN KEY([ParentID])49 REFERENCES [Role] ([ID])50 GO51 52 ALTER TABLE [UserDetail] WITH CHECK ADD CONSTRAINT [FK_UserDetail_User] FOREIGN KEY([ID])53 REFERENCES [User] ([ID])54 ON DELETE CASCADE55 GO56 57 ALTER TABLE [UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_User] FOREIGN KEY([UserID])58 REFERENCES [User] ([ID])59 ON DELETE CASCADE60 GO61 62 ALTER TABLE [UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_Role] FOREIGN KEY([RoleID])63 REFERENCES [Role] ([ID])64 ON DELETE CASCADE65 GO66 67 --创建储存过程68 --SQL Server自关联表无法通过外键设置级联删除,所以专门写一个触发器来完成该工作69 CREATE TRIGGER TRG_Role_Delete70    ON [Role]71    INSTEAD OF DELETE72 AS 73 BEGIN74     -- SET NOCOUNT ON added to prevent extra result sets from75     -- interfering with SELECT statements.76     SET NOCOUNT ON;77 78     DECLARE @ID uniqueidentifier;79     SELECT @ID = ID FROM deleted;80     81     DELETE [Role] WHERE ParentID = @ID;82     DELETE [Role] WHERE ID = @ID;83 END84 GO

使用SQL Server Management Studio工具创建名为“Membership”的数据库,并执行以上的DDL语句,建立本示例所需的数据库对象。

 

实体数据模型

在Visual Studio解决方案的Edm项目中,使用Database First开发模式生成实体数据模型,如下图所示:

 

3自动生成的实体数据模型

可以看到,自动生成的实体数据模型包括两个文件:Membership.edmx和Membership.Designer.cs。

Membership.edmx是使用XML语言进行描述的,在Visual Studio中,用XML(文本)编辑器打开Membership.edmx文件,可以看到该文件的内容结构如下图所示:

 

4 Membership.edmx文件内容结构图

上图清晰地展示了Membership.edmx文件包括四部分内容,分别是SSDL、CSDL、MSL和设计视图内容。设计视图内容部分主要提供实体数据模型可视化编辑工具所需的实体图像的尺寸、位置等信息,本文对此就不做进一步研究了。Membership.edmx是对象-关系映射文件,它是实体数据模型的关键内容。

Membership.Designer.cs是Visual Studio运用T4模板技术,根据CSDL内容生成的后台代码,其内容如下图所示:

 

5 Membership.Designer.cs文件内容结构图

Membership.Designer.cs文件包括上下文和实体两部分内容,对应图1中所示的ObjectContext和Entity。它是上层代码访问实体对象模型的入口,有了它才使实体对象模型变得可用和易用。

一、SSDL

SSDL(Store Schema Definition Language,存储架构定义语言)面向关系,定义数据库对象的架构信息,包括表结构、主外键信息,以及存储过程等。该部分内容根据不同的数据库,会有一定的差异。Membership.edmx文件中SSDL部分的内容如下:

1 
2
3
4
5 … 6
7
8
9
10 …11
12
13
14
15
16
17
18
19
20 …21
22
23
24
25
26
27
28
29
30
31
32
33 …34
35

由上面的代码示例可以看出,SSDL的内容主要包括两大部分:对象容器和对象详细定义。而这两部分均包括了对象(表)和关系(外键)两方面的内容。

二、CSDL

CSDL(Conceptual Schema Definition Language,概念架构定义语言)面向对象,定义概念层实体对象的架构信息,包括实体属性信息及实体间的引用关系。该部分不关心下层所使用的数据库类型,内容始终保持一致。Membership.edmx文件中CSDL部分的内容如下:

1 
2
3
4
5 … 6
7
8
9
10 …11
12
13
14
15
16
17
18
19
20
21 …22
23 …24
25
26
27
28
29
30
31
32
33
34
35
36 …37
38

由上面的代码示例可以看出,CSDL的内容与SSDL其实很类似,主要包括实体容器和实体引用关系两部分。所不同的是,SSDL是针对具体某种数据库的E-R模型进行定义,而CSDL则是针对抽象的实体概念模型进行定义。

三、MSL

MSL(Mapping Specification Language,映射规范语言)实现SSDL和CSDL之间的映射,包括表与实体的映射、字段与属性的映射,以及外键与引用的映射等。Membership.edmx文件中MSL部分的内容如下:

1 
2
3
4
5
6
7
8
9
10
11
12
13 …14
15
16
17
18
19
20
21
22 …23
24
25

由上面的代码示例可以看出,MSL的内容主要是定义SSDL与CSDL的映射关系,其内容主要包括对象与实体、关系与引用的映射。

四、实体

实体是E-R关系在概念层的映射表现,Visual Studio自动生成的实体并不是POCO对象,而是继承自EntityObject对象的分部类,其内容大致如下:

1 [EdmEntityTypeAttribute(NamespaceName="MembershipModel", Name="Role")]  2 [Serializable()]  3 [DataContractAttribute(IsReference=true)]  4 public partial class Role : EntityObject  5 {  6     #region 工厂方法  7     public static Role CreateRole(global::System.Guid id, global::System.String name)  8     {  9         Role role = new Role(); 10         role.ID = id; 11         role.Name = name; 12         return role; 13     } 14 #endregion 15  16     #region 基元属性 17     [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] 18     [DataMemberAttribute()] 19     public global::System.Guid ID 20     { 21         get { return _ID; } 22         set 23         { 24             if (_ID != value) 25             { 26                 OnIDChanging(value); 27                 ReportPropertyChanging("ID"); 28                 _ID = StructuralObject.SetValidValue(value); 29                 ReportPropertyChanged("ID"); 30                 OnIDChanged(); 31             } 32         } 33     } 34     private global::System.Guid _ID; 35     partial void OnIDChanging(global::System.Guid value); 36 partial void OnIDChanged(); 37  38     … 39  40     [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)] 41     [DataMemberAttribute()] 42     public Nullable
ParentID 43 { 44 get { return _ParentID; } 45 set 46 { 47 OnParentIDChanging(value); 48 ReportPropertyChanging("ParentID"); 49 _ParentID = StructuralObject.SetValidValue(value); 50 ReportPropertyChanged("ParentID"); 51 OnParentIDChanged(); 52 } 53 } 54 private Nullable
_ParentID; 55 partial void OnParentIDChanging(Nullable
value); 56 partial void OnParentIDChanged(); 57 #endregion 58 59 #region 导航属性 60 [XmlIgnoreAttribute()] 61 [SoapIgnoreAttribute()] 62 [DataMemberAttribute()] 63 [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "FK_Role_Role", "Children")] 64 public EntityCollection
Children 65 { 66 get 67 { 68 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection
("MembershipModel.FK_Role_Role", "Children"); 69 } 70 set 71 { 72 if ((value != null)) 73 { 74 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection
("MembershipModel.FK_Role_Role", "Children", value); 75 } 76 } 77 } 78 79 [XmlIgnoreAttribute()] 80 [SoapIgnoreAttribute()] 81 [DataMemberAttribute()] 82 [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "FK_Role_Role", "Parent")] 83 public Role Parent 84 { 85 get 86 { 87 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_Role_Role", "Parent").Value; 88 } 89 set 90 { 91 ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_Role_Role", "Parent").Value = value; 92 } 93 } 94 95 [BrowsableAttribute(false)] 96 [DataMemberAttribute()] 97 public EntityReference
ParentReference 98 { 99 get100 {101 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_Role_Role", "Parent");102 }103 set104 {105 if ((value != null))106 {107 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference
("MembershipModel.FK_Role_Role", "Parent", value);108 }109 }110 }111 …112 #endregion113 }

由上面的代码可以看出,实体类主要包括工厂方法、基元属性和导航属性三部分内容。其中基元属性和导航属性与CSDL中定义的实体内容基本一致。此外,实体类还附加了很多特性、事件方法等,在本系列的第5篇延迟加载中,你将了解到所有这些附件的内容,几乎都是用于实现自动延迟加载功能的。

五、ObjectContext

ObjectContext是实体上下文环境,自定义上下文环境需要继承该类,并扩展自定义的实体集,以供上层代码通过它方便的使用实体。自定义ObjectContext类的内容如下:

1 public partial class Membership : ObjectContext 2 { 3     #region 构造函数 4     public Membership() : base("name=Membership", "Membership") 5     { 6         this.ContextOptions.LazyLoadingEnabled = true; 7     } 8      9     public Membership(string connectionString) : base(connectionString, "Membership")10     {11         this.ContextOptions.LazyLoadingEnabled = true;12     }13     14     public Membership(EntityConnection connection) : base(connection, "Membership")15     {16         this.ContextOptions.LazyLoadingEnabled = true;17     }18     #endregion19     20     #region ObjectSet 属性21     22     public ObjectSet
Roles23 {24 get25 {26 if ((_Roles == null))27 {28 _Roles = base.CreateObjectSet
("Roles");29 }30 return _Roles;31 }32 }33 private ObjectSet
_Roles;34 …35 #endregion36 37 #region AddTo 方法38 /// 39 public void AddToRoles(Role role)40 {41 base.AddObject("Roles", role);42 }43 …44 #endregion45 }

由上面的代码可以看出,自定义实体上下文环境类的内容主要包括构造函数、实体集和AddTo方法。其中,构造函数提供使用默认连接配置名、指定连接配置名和指定连接三种方式构造实例;实体集定义该上下文环境可以访问的实体集合,这部分很重要,上层代码都是通过这部分提供的实体集来访问实体对象模型的;AddTo方法是向实体集中新增实体,这部分内容是已经废弃了的,我们可以直接使用实体集的添加方法替换。

另外,还有一部分内容是容易被忽略的,那就是关系源元数据,可以在Membership.Designer.cs文件的开始部分找到它,内容如下:

1 [assembly: EdmSchemaAttribute()]2 #region EDM 关系源元数据3 4 [assembly: EdmRelationshipAttribute("MembershipModel", "FK_Role_Role", "Parent", System.Data.Metadata.Edm.RelationshipMultiplicity.ZeroOrOne, typeof(Apollo.Blog.EF.Chapter3.Edm.Role), "Children", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(Apollo.Blog.EF.Chapter3.Edm.Role), true)]5 [assembly: EdmRelationshipAttribute("MembershipModel", "FK_UserDetail_User", "User", System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(Apollo.Blog.EF.Chapter3.Edm.User), "UserDetail", System.Data.Metadata.Edm.RelationshipMultiplicity.ZeroOrOne, typeof(Apollo.Blog.EF.Chapter3.Edm.UserDetail), true)]6 [assembly: EdmRelationshipAttribute("MembershipModel", "UserRole", "Role", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(Apollo.Blog.EF.Chapter3.Edm.Role), "User", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(Apollo.Blog.EF.Chapter3.Edm.User))]7 8 #endregion

关系源元数据定义了实体对象间引用关系的元数据信息,它是实现自动延迟加载不可或缺的一部分,本系列的第5篇文章将会涉及到该部分内容。

实体数据模型的内容就这么多了。下面提供图1的形象化版本,以帮助你更直观的了解对象-关系映射的实现过程:

 

6对象-关系映射过程图

 

关系映射

众所周知,E-R关系主要包括一对一、一对多和多对多三种,在了解了对象-关系映射的实现过程后,下面就逐一对这三种关系与实体数据模型中的实体引用如何进行映射做进一步的研究。考虑篇幅过长会影响读者对重点内容的关注,后续代码中只摘出关键的、能说明问题的部分进行阐述。

一、一对一

本文示例所用的E-R模型(如图2)中,User和UserDetail对象是一对一的关系。接下来就来看看这两个对象及其关系是如何映射为对应的实体对象模型的。

首先来看SSDL定义,如下所示:

1 
2
3
4 … 5
6
7
8
9
10
11
12
13
14
15 …16
17
18
19
20
21
22 …23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

SSDL的定义包含了User表、UserDetail表和FK_UserDetail_User外键的定义,与前文给定的数据库DDL的定义是一一对应的,不用做过多的解释了。

CSDL定义如下所示:

1 
2
3
4 … 5
6
7
8
9
10
11 …12
13
14
15 …16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

CSDL中也是对实体和引用进行了定义。另外,在实体定义中,加入了导航属性来实现实体引用。这种引用关系是双向的,即你可以在User实体中引用UserDetail实体,也可以在UserDetail实体中引用User实体。其实不只是一对一,一对多、多对多映射也是同样的情况,下文就不再赘述了。

MSL中不需要对一对一映射作任何定义,只是简单的定义表与实体、字段与属性映射关系即可。

关系源元数据如下所示:

1 [assembly: EdmRelationshipAttribute("MembershipModel", "FK_UserDetail_User", "User", System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(Apollo.Blog.EF.Chapter3.Edm.User), "UserDetail", System.Data.Metadata.Edm.RelationshipMultiplicity.ZeroOrOne, typeof(Apollo.Blog.EF.Chapter3.Edm.UserDetail), true)]

实体的内容如下所示:

1 public partial class User : EntityObject 2 { 3     #region 导航属性 4     [XmlIgnoreAttribute()] 5     [SoapIgnoreAttribute()] 6     [DataMemberAttribute()] 7     [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "FK_UserDetail_User", "UserDetail")] 8     public UserDetail UserDetail 9     {10         get11         {12             return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_UserDetail_User", "UserDetail").Value;13 }14 set15 {16 ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_UserDetail_User", "UserDetail").Value = value;17 }18 }19 [BrowsableAttribute(false)]20 [DataMemberAttribute()]21 public EntityReference
UserDetailReference22 {23 get24 {25 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_UserDetail_User", "UserDetail");26 }27 set28 {29 if ((value != null))30 {31 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference
("MembershipModel.FK_UserDetail_User", "UserDetail", value);32 }33 }34 }35 #endregion36 }37 38 [EdmEntityTypeAttribute(NamespaceName="MembershipModel", Name="UserDetail")]39 [Serializable()]40 [DataContractAttribute(IsReference=true)]41 public partial class UserDetail : EntityObject42 {43 #region 导航属性44 [XmlIgnoreAttribute()]45 [SoapIgnoreAttribute()]46 [DataMemberAttribute()]47 [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "FK_UserDetail_User", "User")]48 public User User49 {50 get51 {52 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_UserDetail_User", "User").Value;53 }54 set55 {56 ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_UserDetail_User", "User").Value = value;57 }58 }59 ///
60 /// 没有元数据文档可用。61 /// 62 [BrowsableAttribute(false)]63 [DataMemberAttribute()]64 public EntityReference
UserReference65 {66 get67 {68 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_UserDetail_User", "User");69 }70 set71 {72 if ((value != null))73 {74 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference
("MembershipModel.FK_UserDetail_User", "User", value);75 }76 }77 }78 79 #endregion80 }

可以看到,实体类中除了包括CSDL中定义的导航属性外,还额外定义了一个*Reference属性,该属性是用于实现自动延迟加载的。

二、一对多

Role的Parent和Children是一对多的自关联关系(并不是所有一对多关系都是自关联的,只是本文所使用的E-R模型正好是如此的),下面直接给出实体数据模型各部分关键内容。

SSDL:

1 
2
3
4 … 5
6
7
8
9
10
11 …12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

CSDL:

1 
2
3
4 … 5
6
7
8
9
10 …11
12
13
14 …15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

MSL:MSL中不需要对一对一映射作任何定义,只是简单的定义表与实体、字段与属性映射关系即可。

关系源元数据:

1 [assembly: EdmRelationshipAttribute("MembershipModel", "FK_Role_Role", "Parent", System.Data.Metadata.Edm.RelationshipMultiplicity.ZeroOrOne, typeof(Apollo.Blog.EF.Chapter3.Edm.Role), "Children", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(Apollo.Blog.EF.Chapter3.Edm.Role), true)]

实体:

1 public partial class Role : EntityObject 2 { 3     #region 基元属性 4     … 5     [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)] 6     [DataMemberAttribute()] 7     public Nullable
ParentID 8 { 9 get10 {11 return _ParentID;12 }13 set14 {15 OnParentIDChanging(value);16 ReportPropertyChanging("ParentID");17 _ParentID = StructuralObject.SetValidValue(value);18 ReportPropertyChanged("ParentID");19 OnParentIDChanged();20 }21 }22 private Nullable
_ParentID;23 partial void OnParentIDChanging(Nullable
value);24 partial void OnParentIDChanged();25 #endregion26 27 #region 导航属性 28 [XmlIgnoreAttribute()]29 [SoapIgnoreAttribute()]30 [DataMemberAttribute()]31 [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "FK_Role_Role", "Children")]32 public EntityCollection
Parent33 {34 get35 {36 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection
("MembershipModel.FK_Role_Role", "Children");37 }38 set39 {40 if ((value != null))41 {42 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection
("MembershipModel.FK_Role_Role", "Children", value);43 }44 }45 }46 47 ///
48 /// 没有元数据文档可用。49 /// 50 [XmlIgnoreAttribute()]51 [SoapIgnoreAttribute()]52 [DataMemberAttribute()]53 [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "FK_Role_Role", "Parent")]54 public Role Children55 {56 get57 {58 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_Role_Role", "Parent").Value;59 }60 set61 {62 ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_Role_Role", "Parent").Value = value;63 }64 }65 66 [BrowsableAttribute(false)]67 [DataMemberAttribute()]68 public EntityReference
ChildrenReference69 {70 get71 {72 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference
("MembershipModel.FK_Role_Role", "Parent");73 }74 set75 {76 if ((value != null))77 {78 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference
("MembershipModel.FK_Role_Role", "Parent", value);79 }80 }81 }82 #endregion83 }

三、多对多

User和Role是多对多的关系,下面直接给出实体数据模型各部分关键内容。

SSDL:

1 
2
3
4 … 5
6 … 7
8
9
10
11
12
13
14
15
16 …17
18
19
20
21
22
23
24
25 …26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

CSDL:

1 
2
3
4
5
6 … 7
8
9
10
11
12
13 …14
15
16
17 …18
19
20 …21
22
23
24
25
26

MSL部分需要专门为多对多关系进行映射定义,如下所示:

1 
2
3
4 … 5
6
7
8
9
10
11
12
13
14
15

关系源元数据如下所示:

1 [assembly: EdmRelationshipAttribute("MembershipModel", "UserRole", "Role", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(Apollo.Blog.EF.Chapter3.Edm.Role), "User", System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(Apollo.Blog.EF.Chapter3.Edm.User))]

实体:

1 public partial class Role : EntityObject 2 { 3     … 4 #region 导航属性 5 … 6     [XmlIgnoreAttribute()] 7     [SoapIgnoreAttribute()] 8     [DataMemberAttribute()] 9     [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "UserRole", "User")]10     public EntityCollection
Users11 {12 get13 {14 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection
("MembershipModel.UserRole", "User");15 }16 set17 {18 if ((value != null))19 {20 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection
("MembershipModel.UserRole", "User", value);21 }22 }23 }24 25 #endregion26 }27 28 public partial class User : EntityObject29 {30 …31 #region 导航属性32 …33 [XmlIgnoreAttribute()]34 [SoapIgnoreAttribute()]35 [DataMemberAttribute()]36 [EdmRelationshipNavigationPropertyAttribute("MembershipModel", "UserRole", "Role")]37 public EntityCollection
Roles38 {39 get40 {41 return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection
("MembershipModel.UserRole", "Role");42 }43 set44 {45 if ((value != null))46 {47 ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection
("MembershipModel.UserRole", "Role", value);48 }49 }50 }51 52 #endregion53 }

最后,给出该实体数据模型的简单测试代码,从中可以看出该模型使用起来是很方便和谐的:

1 using (var db = new Membership()) 2 { 3     var role = new Role(); 4     role.ID = Guid.NewGuid(); 5     role.Name = "管理员"; 6  7     var role1 = new Role(); 8     role1.ID = Guid.NewGuid(); 9     role1.Name = "业务管理员";10     role1.Parent = role;11 12     var user = new User();13     user.ID = Guid.NewGuid();14     user.Account = "Apollo";15     user.Password = "123456";16     user.UserDetail = new UserDetail() { ID = user.ID, Name = "Yilin", Sex = "男", Birthday = DateTime.Now };17     user.Roles.Add(role1);18     db.Users.AddObject(user);19 20     db.SaveChanges();21 }

 

总结

本文首先给出了实体数据模型内容结构图,宏观分析了实体数据模型主要由SSDL、CSDL、MSL、实体和ObjectContext几部分组成;紧接着通过一个实例逐一分析了这几部分的详细内容;最后详细讲解了如何使用Entity Framework技术将一对一、一对多和多对多三种E-R关系映射为实体数据模型。

下一篇文章将在本文的基础上,探讨如何驾驭实体数据模型的各组成内容,将Entity Framework技术灵活应用到项目开发中。

 

转载于:https://www.cnblogs.com/yilin/archive/2013/02/26/apollo_blog_ef_chapter3.html

你可能感兴趣的文章
BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
查看>>
四种方法校验数组中是否包含某个指定的字符串
查看>>
29、Java并发性和多线程-非阻塞算法
查看>>
安装OpenResty开发环境
查看>>
第0课 从0开始
查看>>
hadoop无法启动DataNode问题
查看>>
java泛型中<?>和<T>区别
查看>>
这里是指推送通知跟NSNotification有区别:
查看>>
用户ID的代码生成
查看>>
win7经常出现“关闭xxxx前您必须关闭所有会话框”
查看>>
SNMP安全配置的两种方法(也可同一时候兼顾配置两种方法)
查看>>
MongoDB 自己定义函数
查看>>
Summary Day30
查看>>
逆向输出回环数组
查看>>
自己动手,实现“你的名字”滤镜
查看>>
高清摄像头MIPI CSI2接口浅解【转】
查看>>
C# CancellationTokenSource和CancellationToken的实现
查看>>
PCIE BAR空间
查看>>
winform命名规范
查看>>
如何用数学课件制作工具画角平分线
查看>>