Entity Framework技術系列之4:靈活應用實體數據模型

前言

上一篇文章中,我詳細解析了使用Database First和Model First開發模式自動生成的Entity Framework實體數據模型的內容結構,如下圖所示:

 

圖1實體數據模型內容結構圖

本文將就實體數據模型內容作文章,將其拆分爲多個文件,並作適當的調整,實現一個DIY的實體數據模型,其內容結構如下圖所示:

 

圖2調整後的實體數據模型內容結構圖

做這些調整的目的有兩個,其一是使用POCO替換實體數據模型中繁瑣的實體類,使代碼更整潔並易於維護;其二是使程序支持多種數據庫,並且易於擴展。

 

E-R模型

E-R模型繼續沿用上一篇文章中使用的模型,如下圖所示:

 

圖3 E-R模型

對應的SQL Server 數據庫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 GO
13 
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 GO
20 
21 CREATE TABLE [UserRole](
22     [UserID] [uniqueidentifier] NOT NULL,
23     [RoleID] [uniqueidentifier] NOT NULL)
24 GO
25 
26 --創建主鍵
27 ALTER TABLE [Role]
28 ADD CONSTRAINT [PK_Role]
29     PRIMARY KEY CLUSTERED ([ID] ASC);
30 GO
31 
32 ALTER TABLE [User]
33 ADD CONSTRAINT [PK_User]
34     PRIMARY KEY CLUSTERED ([ID] ASC);
35 GO
36 
37 ALTER TABLE [UserDetail]
38 ADD CONSTRAINT [PK_UserDetail]
39     PRIMARY KEY CLUSTERED ([ID] ASC);
40 GO
41 
42 ALTER TABLE [UserRole]
43 ADD CONSTRAINT [PK_UserRole]
44     PRIMARY KEY CLUSTERED ([UserID] ASC, RoleID ASC);
45 GO
46 
47 --創建外鍵
48 ALTER TABLE [Role] WITH CHECK ADD CONSTRAINT [FK_Role_Role] FOREIGN KEY([ParentID])
49 REFERENCES [Role] ([ID])
50 GO
51 
52 ALTER TABLE [UserDetail] WITH CHECK ADD CONSTRAINT [FK_UserDetail_User] FOREIGN KEY([ID])
53 REFERENCES [User] ([ID])
54 ON DELETE CASCADE
55 GO
56 
57 ALTER TABLE [UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_User] FOREIGN KEY([UserID])
58 REFERENCES [User] ([ID])
59 ON DELETE CASCADE
60 GO
61 
62 ALTER TABLE [UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_Role] FOREIGN KEY([RoleID])
63 REFERENCES [Role] ([ID])
64 ON DELETE CASCADE
65 GO
66 
67 --創建儲存過程
68 --SQL Server自關聯表無法通過外鍵設置級聯刪除,所以專門寫一個觸發器來完成該工作
69 CREATE TRIGGER TRG_Role_Delete
70    ON [Role]
71    INSTEAD OF DELETE
72 AS 
73 BEGIN
74     -- SET NOCOUNT ON added to prevent extra result sets from
75     -- 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 END
84 GO
複製代碼

使用SQL Server Management Studio工具創建名爲“Membership”的數據庫,並執行以上的DDL語句,建立本示例所需的數據庫對象。

 

DIY實體數據模型

接下來將對前文中的實體數據模型內容進行靈活的調整,使其支持POCO和多數據庫,調整的內容包括:

  • 將Membership.Designer.cs文件中的上下文環境類放入單獨的EntityContext.cs文件中,並只保留構造函數和實體集屬性兩部分內容;
  • 直接定義Role、User和UserDetail三個POCO實體類;
  • 將Membership.edmx文件中CSDL、MSL和SSDL的內容分別放入Membership.csdl、Membership.msl和Membership.SqlServer.ssdl三個XML文件中;
  • 複製Membership.SqlServer.ssdl文件爲Membership.MySQL.ssdl文件,並依據MySQL數據庫SQL方言,替換相應的數據類型。

一、實體上下文環境

複製代碼
 1 public class EntityContext : ObjectContext
 2 {
 3     public EntityContext() : this("name=Membership")
 4     {
 5         this.ContextOptions.LazyLoadingEnabled = true;
 6     }
 7     
 8     public EntityContext(string connectionString) : base(connectionString, "Membership")
 9     {
10         this.ContextOptions.LazyLoadingEnabled = true;
11     }
12     
13     public EntityContext(EntityConnection connection) : base(connection, "Membership")
14     {
15         this.ContextOptions.LazyLoadingEnabled = true;
16     }
17 
18     private ObjectSet<Role> roles;
19     public ObjectSet<Role> Roles
20     {
21         get
22         {
23             if ((roles == null))
24                 roles = base.CreateObjectSet<Role>("Roles");
25 
26             return roles;
27         }
28     }
29     
30     private ObjectSet<User> users;
31     public ObjectSet<User> Users
32     {
33         get
34         {
35             if ((users == null))
36             {
37                 users = base.CreateObjectSet<User>("Users");
38             }
39             return users;
40         }
41     }
42     
43     private ObjectSet<UserDetail> userDetails;
44     public ObjectSet<UserDetail> UserDetails
45     {
46         get
47         {
48             if ((userDetails == null))
49             {
50                 userDetails = base.CreateObjectSet<UserDetail>("UserDetails");
51             }
52             return userDetails;
53         }
54     }
55 }
複製代碼

二、實體類

Role實體類:

複製代碼
 1 public class Role
 2 {
 3     public Guid ID { get; set; }
 4 
 5     public string Name { get; set; }
 6 
 7     public Guid? ParentID { get; set; }
 8 
 9     public Role Parent { get; set; }
10 
11     public IList<Role> Children { get; set; }
12 
13     public IList<User> Users { get; set; }
14 }
複製代碼

User實體類:

複製代碼
 1 public class User
 2 {
 3     public Guid ID { get; set; }
 4 
 5     public string Account { get; set; }
 6 
 7     public string Password { get; set; }
 8 
 9     public UserDetail UserDetail { get; set; }
10 
11     public IList<Role> Roles { get; set; }
12 }
複製代碼

UserDetail實體類:

複製代碼
 1 public class UserDetail
 2 {
 3     public Guid ID { get; set; }
 4 
 5     public string Name { get; set; }
 6 
 7     public string Sex { get; set; }
 8 
 9     public DateTime Birthday { get; set; }
10 
11     public User User { get; set; }
12 }
複製代碼

三、CSDL

複製代碼
 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <Schema Namespace="MembershipModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
 3   <EntityContainer Name="Membership" annotation:LazyLoadingEnabled="true">
 4     <EntitySet Name="Roles" EntityType="MembershipModel.Role" />
 5     <EntitySet Name="Users" EntityType="MembershipModel.User" />
 6     <EntitySet Name="UserDetails" EntityType="MembershipModel.UserDetail" />
 7     <AssociationSet Name="FK_Role_Role" Association="MembershipModel.FK_Role_Role">
 8       <End Role="Parent" EntitySet="Roles" />
 9       <End Role="Children" EntitySet="Roles" />
10     </AssociationSet>
11     <AssociationSet Name="FK_UserDetail_User" Association="MembershipModel.FK_UserDetail_User">
12       <End Role="User" EntitySet="Users" />
13       <End Role="UserDetail" EntitySet="UserDetails" />
14     </AssociationSet>
15     <AssociationSet Name="UserRole" Association="MembershipModel.UserRole">
16       <End Role="Role" EntitySet="Roles" />
17       <End Role="User" EntitySet="Users" />
18     </AssociationSet>
19   </EntityContainer>
20   <EntityType Name="Role">
21     <Key>
22       <PropertyRef Name="ID" />
23     </Key>
24     <Property Name="ID" Type="Guid" Nullable="false" />
25     <Property Name="Name" Type="String" Nullable="false" MaxLength="40" Unicode="true" FixedLength="false" />
26     <Property Name="ParentID" Type="Guid" />
27     <NavigationProperty Name="Children" Relationship="MembershipModel.FK_Role_Role" FromRole="Parent" ToRole="Children" />
28     <NavigationProperty Name="Parent" Relationship="MembershipModel.FK_Role_Role" FromRole="Children" ToRole="Parent" />
29     <NavigationProperty Name="Users" Relationship="MembershipModel.UserRole" FromRole="Role" ToRole="User" />
30   </EntityType>
31   <EntityType Name="User">
32     <Key>
33       <PropertyRef Name="ID" />
34     </Key>
35     <Property Name="ID" Type="Guid" Nullable="false" />
36     <Property Name="Account" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
37     <Property Name="Password" Type="String" Nullable="false" MaxLength="50" Unicode="false" FixedLength="false" />
38     <NavigationProperty Name="UserDetail" Relationship="MembershipModel.FK_UserDetail_User" FromRole="User" ToRole="UserDetail" />
39     <NavigationProperty Name="Roles" Relationship="MembershipModel.UserRole" FromRole="User" ToRole="Role" />
40   </EntityType>
41   <EntityType Name="UserDetail">
42     <Key>
43       <PropertyRef Name="ID" />
44     </Key>
45     <Property Name="ID" Type="Guid" Nullable="false" />
46     <Property Name="Name" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
47     <Property Name="Sex" Type="String" MaxLength="2" Unicode="true" FixedLength="false" />
48     <Property Name="Birthday" Type="DateTime" />
49     <NavigationProperty Name="User" Relationship="MembershipModel.FK_UserDetail_User" FromRole="UserDetail" ToRole="User" />
50   </EntityType>
51   <Association Name="FK_Role_Role">
52     <End Role="Parent" Type="MembershipModel.Role" Multiplicity="0..1" />
53     <End Role="Children" Type="MembershipModel.Role" Multiplicity="*" />
54     <ReferentialConstraint>
55       <Principal Role="Parent">
56         <PropertyRef Name="ID" />
57       </Principal>
58       <Dependent Role="Children">
59         <PropertyRef Name="ParentID" />
60       </Dependent>
61     </ReferentialConstraint>
62   </Association>
63   <Association Name="FK_UserDetail_User">
64     <End Role="User" Type="MembershipModel.User" Multiplicity="1">
65       <OnDelete Action="Cascade" />
66     </End>
67     <End Role="UserDetail" Type="MembershipModel.UserDetail" Multiplicity="0..1" />
68     <ReferentialConstraint>
69       <Principal Role="User">
70         <PropertyRef Name="ID" />
71       </Principal>
72       <Dependent Role="UserDetail">
73         <PropertyRef Name="ID" />
74       </Dependent>
75     </ReferentialConstraint>
76   </Association>
77   <Association Name="UserRole">
78     <End Role="Role" Type="MembershipModel.Role" Multiplicity="*" />
79     <End Role="User" Type="MembershipModel.User" Multiplicity="*" />
80   </Association>
81 </Schema>
複製代碼

四、MSL

複製代碼
 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
 3   <EntityContainerMapping StorageEntityContainer="MembershipModelStoreContainer" CdmEntityContainer="Membership">
 4     <EntitySetMapping Name="Roles">
 5       <EntityTypeMapping TypeName="MembershipModel.Role">
 6         <MappingFragment StoreEntitySet="Role">
 7           <ScalarProperty Name="ID" ColumnName="ID" />
 8           <ScalarProperty Name="Name" ColumnName="Name" />
 9           <ScalarProperty Name="ParentID" ColumnName="ParentID" />
10         </MappingFragment>
11       </EntityTypeMapping>
12     </EntitySetMapping>
13     <EntitySetMapping Name="Users">
14       <EntityTypeMapping TypeName="MembershipModel.User">
15         <MappingFragment StoreEntitySet="User">
16           <ScalarProperty Name="ID" ColumnName="ID" />
17           <ScalarProperty Name="Account" ColumnName="Account" />
18           <ScalarProperty Name="Password" ColumnName="Password" />
19         </MappingFragment>
20       </EntityTypeMapping>
21     </EntitySetMapping>
22     <EntitySetMapping Name="UserDetails">
23       <EntityTypeMapping TypeName="MembershipModel.UserDetail">
24         <MappingFragment StoreEntitySet="UserDetail">
25           <ScalarProperty Name="ID" ColumnName="ID" />
26           <ScalarProperty Name="Name" ColumnName="Name" />
27           <ScalarProperty Name="Sex" ColumnName="Sex" />
28           <ScalarProperty Name="Birthday" ColumnName="Birthday" />
29         </MappingFragment>
30       </EntityTypeMapping>
31     </EntitySetMapping>
32     <AssociationSetMapping Name="UserRole" TypeName="MembershipModel.UserRole" StoreEntitySet="UserRole">
33       <EndProperty Name="Role">
34         <ScalarProperty Name="ID" ColumnName="RoleID" />
35       </EndProperty>
36       <EndProperty Name="User">
37         <ScalarProperty Name="ID" ColumnName="UserID" />
38       </EndProperty>
39     </AssociationSetMapping>
40   </EntityContainerMapping>
41 </Mapping>
複製代碼

五、SSDL

Membership.SqlServer.ssdl

複製代碼
  1 <?xml version="1.0" encoding="utf-8" ?>
  2 <Schema Namespace="MembershipModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
  3   <EntityContainer Name="MembershipModelStoreContainer">
  4     <EntitySet Name="Role" EntityType="MembershipModel.Store.Role" store:Type="Tables" Schema="dbo" />
  5     <EntitySet Name="User" EntityType="MembershipModel.Store.User" store:Type="Tables" Schema="dbo" />
  6     <EntitySet Name="UserDetail" EntityType="MembershipModel.Store.UserDetail" store:Type="Tables" Schema="dbo" />
  7     <EntitySet Name="UserRole" EntityType="MembershipModel.Store.UserRole" store:Type="Tables" Schema="dbo" />
  8     <AssociationSet Name="FK_Role_Role" Association="MembershipModel.Store.FK_Role_Role">
  9       <End Role="Parent" EntitySet="Role" />
 10       <End Role="Children" EntitySet="Role" />
 11     </AssociationSet>
 12     <AssociationSet Name="FK_UserDetail_User" Association="MembershipModel.Store.FK_UserDetail_User">
 13       <End Role="User" EntitySet="User" />
 14       <End Role="UserDetail" EntitySet="UserDetail" />
 15     </AssociationSet>
 16     <AssociationSet Name="FK_UserRole_Role" Association="MembershipModel.Store.FK_UserRole_Role">
 17       <End Role="Role" EntitySet="Role" />
 18       <End Role="UserRole" EntitySet="UserRole" />
 19     </AssociationSet>
 20     <AssociationSet Name="FK_UserRole_User" Association="MembershipModel.Store.FK_UserRole_User">
 21       <End Role="User" EntitySet="User" />
 22       <End Role="UserRole" EntitySet="UserRole" />
 23     </AssociationSet>
 24   </EntityContainer>
 25   <EntityType Name="Role">
 26     <Key>
 27       <PropertyRef Name="ID" />
 28     </Key>
 29     <Property Name="ID" Type="uniqueidentifier" Nullable="false" />
 30     <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="40" />
 31     <Property Name="ParentID" Type="uniqueidentifier" />
 32   </EntityType>
 33   <EntityType Name="User">
 34     <Key>
 35       <PropertyRef Name="ID" />
 36     </Key>
 37     <Property Name="ID" Type="uniqueidentifier" Nullable="false" />
 38     <Property Name="Account" Type="nvarchar" Nullable="false" MaxLength="50" />
 39     <Property Name="Password" Type="varchar" Nullable="false" MaxLength="50" />
 40   </EntityType>
 41   <EntityType Name="UserDetail">
 42     <Key>
 43       <PropertyRef Name="ID" />
 44     </Key>
 45     <Property Name="ID" Type="uniqueidentifier" Nullable="false" />
 46     <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" />
 47     <Property Name="Sex" Type="nvarchar" MaxLength="2" />
 48     <Property Name="Birthday" Type="datetime" />
 49   </EntityType>
 50   <EntityType Name="UserRole">
 51     <Key>
 52       <PropertyRef Name="UserID" />
 53       <PropertyRef Name="RoleID" />
 54     </Key>
 55     <Property Name="UserID" Type="uniqueidentifier" Nullable="false" />
 56     <Property Name="RoleID" Type="uniqueidentifier" Nullable="false" />
 57   </EntityType>
 58   <Association Name="FK_Role_Role">
 59     <End Role="Parent" Type="MembershipModel.Store.Role" Multiplicity="0..1" />
 60     <End Role="Children" Type="MembershipModel.Store.Role" Multiplicity="*" />
 61     <ReferentialConstraint>
 62       <Principal Role="Parent">
 63         <PropertyRef Name="ID" />
 64       </Principal>
 65       <Dependent Role="Children">
 66         <PropertyRef Name="ParentID" />
 67       </Dependent>
 68     </ReferentialConstraint>
 69   </Association>
 70   <Association Name="FK_UserDetail_User">
 71     <End Role="User" Type="MembershipModel.Store.User" Multiplicity="1">
 72       <OnDelete Action="Cascade" />
 73     </End>
 74     <End Role="UserDetail" Type="MembershipModel.Store.UserDetail" Multiplicity="0..1" />
 75     <ReferentialConstraint>
 76       <Principal Role="User">
 77         <PropertyRef Name="ID" />
 78       </Principal>
 79       <Dependent Role="UserDetail">
 80         <PropertyRef Name="ID" />
 81       </Dependent>
 82     </ReferentialConstraint>
 83   </Association>
 84   <Association Name="FK_UserRole_Role">
 85     <End Role="Role" Type="MembershipModel.Store.Role" Multiplicity="1">
 86       <OnDelete Action="Cascade" />
 87     </End>
 88     <End Role="UserRole" Type="MembershipModel.Store.UserRole" Multiplicity="*" />
 89     <ReferentialConstraint>
 90       <Principal Role="Role">
 91         <PropertyRef Name="ID" />
 92       </Principal>
 93       <Dependent Role="UserRole">
 94         <PropertyRef Name="RoleID" />
 95       </Dependent>
 96     </ReferentialConstraint>
 97   </Association>
 98   <Association Name="FK_UserRole_User">
 99     <End Role="User" Type="MembershipModel.Store.User" Multiplicity="1">
100       <OnDelete Action="Cascade" />
101     </End>
102     <End Role="UserRole" Type="MembershipModel.Store.UserRole" Multiplicity="*" />
103     <ReferentialConstraint>
104       <Principal Role="User">
105         <PropertyRef Name="ID" />
106       </Principal>
107       <Dependent Role="UserRole">
108         <PropertyRef Name="UserID" />
109       </Dependent>
110     </ReferentialConstraint>
111   </Association>
112 </Schema>
複製代碼

 

模型應用

首先需要在應用程序配置文件中配置數據連接:

複製代碼
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3   <connectionStrings>
4     <!--SQL Server-->
5     <add name="Membership" providerName="System.Data.EntityClient" connectionString="provider=System.Data.SqlClient;provider connection string=&quot; Data Source=localhost; User Id=sa; Password=11111111; Initial Catalog=Membership; Integrated Security=False;&quot;; metadata=..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.SqlServer.ssdl|..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.csdl|..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.msl"/>
6   </connectionStrings>
7 </configuration>
複製代碼

然後就可以使用該實體數據模型了,測試示例代碼如下:

複製代碼
 1 using (var db  = new EntityContext())
 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     db.Roles.AddObject(role1);
12 
13     db.SaveChanges();
14 }
複製代碼

 

多數據庫支持

下面以擴展對MySQL數據庫支持爲例,講解該實體數據模型如何實現對多種數據庫的支持。需要做以下三件事情:

首先,編寫MySQL數據庫的DDL語句,並執行它以生成數據庫(我是使用Navicat工具連接MySQL,創建Membership數據庫,然後執行DDL語句)。DDL語句如下:

複製代碼
 1 CREATE TABLE `Role` (
 2   `ID` char(36) NOT NULL,
 3   `Name` varchar(40) NOT NULL,
 4   `ParentID` char(36) NULL,
 5   PRIMARY KEY (`ID`),
 6   KEY `ParentID` (`ParentID`),
 7   CONSTRAINT `FK_Role_Role` FOREIGN KEY (`ParentID`) REFERENCES `Role` (`ID`) ON DELETE CASCADE
 8 );
 9 
10 CREATE TABLE `User` (
11   `ID` char(36)  NOT NULL,
12   `Account` varchar(50) NOT NULL,
13   `Password` varchar(50) NOT NULL,
14   PRIMARY KEY (`ID`)
15 );
16 
17 CREATE TABLE `UserDetail` (
18   `ID` char(36) NOT NULL,
19   `Name` varchar(50) NOT NULL,
20   `Sex` varchar(2) NULL,
21   `Birthday` datetime DEFAULT NULL,
22   PRIMARY KEY (`ID`),
23   CONSTRAINT `FK_UserDetail_User` FOREIGN KEY (`ID`) REFERENCES `user` (`ID`) ON DELETE CASCADE
24 );
25 
26 CREATE TABLE `UserRole` (
27   `UserID` char(36) NOT NULL,
28   `RoleID` char(36) NOT NULL,
29   PRIMARY KEY (`UserID`,`RoleID`),
30   KEY `FK_UserRole_Role` (`RoleID`),
31   CONSTRAINT `FK_UserRole_User` FOREIGN KEY (`UserID`) REFERENCES `User` (`ID`) ON DELETE CASCADE,
32   CONSTRAINT `FK_UserRole_Role` FOREIGN KEY (`RoleID`) REFERENCES `Role` (`ID`) ON DELETE CASCADE
33 );
複製代碼

然後,添加Membership.MySQL.ssdl文件,其內容與Membership.SqlServer.ssdl的差別主要體現在提供程序及其版本、數據類型上,如下內容中的高亮標識所示:

複製代碼
  1 <?xml version="1.0" encoding="utf-8" ?>
  2 <Schema Namespace="MembershipModel.Store" Alias="Self" Provider="MySql.Data.MySqlClient" ProviderManifestToken="5.5" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
  3   <EntityContainer Name="MembershipModelStoreContainer">
  4     <EntitySet Name="Role" EntityType="MembershipModel.Store.Role" store:Type="Tables" Schema="dbo" />
  5     <EntitySet Name="User" EntityType="MembershipModel.Store.User" store:Type="Tables" Schema="dbo" />
  6     <EntitySet Name="UserDetail" EntityType="MembershipModel.Store.UserDetail" store:Type="Tables" Schema="dbo" />
  7     <EntitySet Name="UserRole" EntityType="MembershipModel.Store.UserRole" store:Type="Tables" Schema="dbo" />
  8     <AssociationSet Name="FK_Role_Role" Association="MembershipModel.Store.FK_Role_Role">
  9       <End Role="Parent" EntitySet="Role" />
 10       <End Role="Children" EntitySet="Role" />
 11     </AssociationSet>
 12     <AssociationSet Name="FK_UserDetail_User" Association="MembershipModel.Store.FK_UserDetail_User">
 13       <End Role="User" EntitySet="User" />
 14       <End Role="UserDetail" EntitySet="UserDetail" />
 15     </AssociationSet>
 16     <AssociationSet Name="FK_UserRole_Role" Association="MembershipModel.Store.FK_UserRole_Role">
 17       <End Role="Role" EntitySet="Role" />
 18       <End Role="UserRole" EntitySet="UserRole" />
 19     </AssociationSet>
 20     <AssociationSet Name="FK_UserRole_User" Association="MembershipModel.Store.FK_UserRole_User">
 21       <End Role="User" EntitySet="User" />
 22       <End Role="UserRole" EntitySet="UserRole" />
 23     </AssociationSet>
 24   </EntityContainer>
 25   <EntityType Name="Role">
 26     <Key>
 27       <PropertyRef Name="ID" />
 28     </Key>
 29     <Property Name="ID" Type="guid" Nullable="false" />
 30     <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="40" />
 31     <Property Name="ParentID" Type="guid" />
 32   </EntityType>
 33   <EntityType Name="User">
 34     <Key>
 35       <PropertyRef Name="ID" />
 36     </Key>
 37     <Property Name="ID" Type="guid" Nullable="false" />
 38     <Property Name="Account" Type="nvarchar" Nullable="false" MaxLength="50" />
 39     <Property Name="Password" Type="varchar" Nullable="false" MaxLength="50" />
 40   </EntityType>
 41   <EntityType Name="UserDetail">
 42     <Key>
 43       <PropertyRef Name="ID" />
 44     </Key>
 45     <Property Name="ID" Type="guid" Nullable="false" />
 46     <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" />
 47     <Property Name="Sex" Type="nvarchar" MaxLength="2" />
 48     <Property Name="Birthday" Type="datetime" />
 49   </EntityType>
 50   <EntityType Name="UserRole">
 51     <Key>
 52       <PropertyRef Name="UserID" />
 53       <PropertyRef Name="RoleID" />
 54     </Key>
 55     <Property Name="UserID" Type="guid" Nullable="false" />
 56     <Property Name="RoleID" Type="guid" Nullable="false" />
 57   </EntityType>
 58   <Association Name="FK_Role_Role">
 59     <End Role="Parent" Type="MembershipModel.Store.Role" Multiplicity="0..1" />
 60     <End Role="Children" Type="MembershipModel.Store.Role" Multiplicity="*" />
 61     <ReferentialConstraint>
 62       <Principal Role="Parent">
 63         <PropertyRef Name="ID" />
 64       </Principal>
 65       <Dependent Role="Children">
 66         <PropertyRef Name="ParentID" />
 67       </Dependent>
 68     </ReferentialConstraint>
 69   </Association>
 70   <Association Name="FK_UserDetail_User">
 71     <End Role="User" Type="MembershipModel.Store.User" Multiplicity="1">
 72       <OnDelete Action="Cascade" />
 73     </End>
 74     <End Role="UserDetail" Type="MembershipModel.Store.UserDetail" Multiplicity="0..1" />
 75     <ReferentialConstraint>
 76       <Principal Role="User">
 77         <PropertyRef Name="ID" />
 78       </Principal>
 79       <Dependent Role="UserDetail">
 80         <PropertyRef Name="ID" />
 81       </Dependent>
 82     </ReferentialConstraint>
 83   </Association>
 84   <Association Name="FK_UserRole_Role">
 85     <End Role="Role" Type="MembershipModel.Store.Role" Multiplicity="1">
 86       <OnDelete Action="Cascade" />
 87     </End>
 88     <End Role="UserRole" Type="MembershipModel.Store.UserRole" Multiplicity="*" />
 89     <ReferentialConstraint>
 90       <Principal Role="Role">
 91         <PropertyRef Name="ID" />
 92       </Principal>
 93       <Dependent Role="UserRole">
 94         <PropertyRef Name="RoleID" />
 95       </Dependent>
 96     </ReferentialConstraint>
 97   </Association>
 98   <Association Name="FK_UserRole_User">
 99     <End Role="User" Type="MembershipModel.Store.User" Multiplicity="1">
100       <OnDelete Action="Cascade" />
101     </End>
102     <End Role="UserRole" Type="MembershipModel.Store.UserRole" Multiplicity="*" />
103     <ReferentialConstraint>
104       <Principal Role="User">
105         <PropertyRef Name="ID" />
106       </Principal>
107       <Dependent Role="UserRole">
108         <PropertyRef Name="UserID" />
109       </Dependent>
110     </ReferentialConstraint>
111   </Association>
112 </Schema>
複製代碼

配置文件中加入MySQL連接字符串,以及MySQL數據庫提供程序工廠,添加後的應用程序配置文件內容如下:

複製代碼
 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3   <connectionStrings>
 4     <!--SQL Server-->
 5     <add name="Membership" providerName="System.Data.EntityClient" connectionString="provider=System.Data.SqlClient;provider connection string=&quot; Data Source=localhost; User Id=sa; Password=11111111; Initial Catalog=Membership; Integrated Security=False;&quot;; metadata=..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.SqlServer.ssdl|..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.csdl|..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.msl"/>
 6     <!--MySQL
 7     <add name="Membership" providerName="System.Data.EntityClient" connectionString="provider=MySql.Data.MySqlClient; provider connection string=&quot; Data Source=localhost; User Id=root; Password=11111111; Initial Catalog=Membership; Integrated Security=False;&quot;; metadata=..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.MySQL.ssdl|..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.csdl|..\..\..\Apollo.Blog.EF.Chapter4.Edm\Mapping\Membership.msl"/>-->
 8   </connectionStrings>
 9   <system.data>
10     <DbProviderFactories>
11       <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory,MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
12     </DbProviderFactories>
13   </system.data>
14 </configuration>
複製代碼

通過切換SQL Server和MySQL連接字符串的啓用和註釋狀態,就可以實現不同數據庫的支持切換了。

 

補充說明

一、關於數據庫生成

Entity Framework技術提供了由實體數據模型直接生成數據庫的功能,示例代碼如下:

1 using (var db = new EntityContext())
2 {
3     if (!db.DatabaseExists())
4         db.CreateDatabase();
5 }

但是,通過該方式自動生成數據庫至少存在以下兩個問題或不足:

  • 生成的外鍵不能級聯刪除,這會導致有外鍵的對象刪除出錯;
  • 不支持複雜的DDL語句功能,比如無法生成存儲過程、觸發器等。

所以,我建議不要使用該方式自動生成數據庫,雖然它看起來貌似很好很強大。

二、關於映射文件的生成操作

將Membership.edmx文件拆分成SSDL、CSDL和MSL三個單獨的文件後,將這三個文件設爲“嵌入的資源”,然後在應用配置文件的數據庫連接字符串中使用如下的方式查找文件似乎行不通,總是報“無法加載指定的元數據資源”錯誤,所以本文選擇了使用文件的相對路徑進行查找:

1 metadata=res://*/Membership.csdl|res://*/Membership.ssdl|res://*/Membership.msl

 

總結

本文在前文深入瞭解實體數據模型的基礎上,對該模型作了些許調整,實現了一個DIY的實體數據模型。該實體數據模型能夠很好的支持POCO和多數據庫,易於維護和擴展。但是該模型無法實現自動延遲加載,這算是美中不足之處。在本系列的第6篇中,將對延遲加載做專門討論,屆時將會告訴你如何使用該DIY實體數據模型實現手動延遲加載;以及如何修改該模型,使其支持延遲加載。

下一篇文章將討論如何在本文的基礎上實現關聯數據的延遲加載。

發佈了7 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章