在使用EF时,发现实体之间有个继承的关系。所以想到是不是可以将一些通用的字段作为基类,例如每个实体都有版本号、创建者等字段。所以采用以下Modle first 方式实现。
首先创建Model
当然在创建Model的时候,需要注意只用基类才可以申明主键。
保存-由实体生成数据库
1 -- -------------------------------------------------- 2 -- Entity Designer DDL Script for SQL Server 2005, 2008, 2012 and Azure 3 -- -------------------------------------------------- 4 -- Date Created: 07/17/2018 12:11:28 5 -- Generated from EDMX file: E:\Test\SimpleTest\SimpleTest.Entity\TestSystem.edmx 6 -- -------------------------------------------------- 7 8 SET QUOTED_IDENTIFIER OFF; 9 GO 10 USE [TestSystem]; 11 GO 12 IF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]'); 13 GO 14 15 -- -------------------------------------------------- 16 -- Dropping existing FOREIGN KEY constraints 17 -- -------------------------------------------------- 18 19 IF OBJECT_ID(N'[dbo].[FK_Account_inherits_BaseEntity]', 'F') IS NOT NULL 20 ALTER TABLE [dbo].[BaseEntity_Account] DROP CONSTRAINT [FK_Account_inherits_BaseEntity]; 21 GO 22 IF OBJECT_ID(N'[dbo].[FK_Product_inherits_BaseEntity]', 'F') IS NOT NULL 23 ALTER TABLE [dbo].[BaseEntity_Product] DROP CONSTRAINT [FK_Product_inherits_BaseEntity]; 24 GO 25 26 -- -------------------------------------------------- 27 -- Dropping existing tables 28 -- -------------------------------------------------- 29 30 IF OBJECT_ID(N'[dbo].[BaseEntity]', 'U') IS NOT NULL 31 DROP TABLE [dbo].[BaseEntity]; 32 GO 33 IF OBJECT_ID(N'[dbo].[BaseEntity_Account]', 'U') IS NOT NULL 34 DROP TABLE [dbo].[BaseEntity_Account]; 35 GO 36 IF OBJECT_ID(N'[dbo].[BaseEntity_Product]', 'U') IS NOT NULL 37 DROP TABLE [dbo].[BaseEntity_Product]; 38 GO 39 40 -- -------------------------------------------------- 41 -- Creating all tables 42 -- -------------------------------------------------- 43 44 -- Creating table 'BaseEntity' 45 CREATE TABLE [dbo].[BaseEntity] ( 46 [Id] int IDENTITY(1,1) NOT NULL, 47 [CreateId] int NOT NULL, 48 [CreateTime] datetime NOT NULL, 49 [LastModifierId] int NOT NULL, 50 [LastModifyTime] datetime NOT NULL, 51 [Version] int NOT NULL 52 ); 53 GO 54 55 -- Creating table 'BaseEntity_Account' 56 CREATE TABLE [dbo].[BaseEntity_Account] ( 57 [Name] nvarchar(max) NOT NULL, 58 [AppKeyId] nvarchar(max) NOT NULL, 59 [AppSecretKey] nvarchar(max) NOT NULL, 60 [MarketPlaceId] nvarchar(max) NOT NULL, 61 [Id] int NOT NULL 62 ); 63 GO 64 65 -- Creating table 'BaseEntity_Product' 66 CREATE TABLE [dbo].[BaseEntity_Product] ( 67 [Code] nvarchar(max) NOT NULL, 68 [Title] nvarchar(max) NOT NULL, 69 [Description] nvarchar(max) NOT NULL, 70 [Price] decimal(18,0) NOT NULL, 71 [Weight] decimal(18,0) NOT NULL, 72 [Id] int NOT NULL 73 ); 74 GO 75 76 -- -------------------------------------------------- 77 -- Creating all PRIMARY KEY constraints 78 -- -------------------------------------------------- 79 80 -- Creating primary key on [Id] in table 'BaseEntity' 81 ALTER TABLE [dbo].[BaseEntity] 82 ADD CONSTRAINT [PK_BaseEntity] 83 PRIMARY KEY CLUSTERED ([Id] ASC); 84 GO 85 86 -- Creating primary key on [Id] in table 'BaseEntity_Account' 87 ALTER TABLE [dbo].[BaseEntity_Account] 88 ADD CONSTRAINT [PK_BaseEntity_Account] 89 PRIMARY KEY CLUSTERED ([Id] ASC); 90 GO 91 92 -- Creating primary key on [Id] in table 'BaseEntity_Product' 93 ALTER TABLE [dbo].[BaseEntity_Product] 94 ADD CONSTRAINT [PK_BaseEntity_Product] 95 PRIMARY KEY CLUSTERED ([Id] ASC); 96 GO 97 98 -- -------------------------------------------------- 99 -- Creating all FOREIGN KEY constraints 100 -- -------------------------------------------------- 101 102 -- Creating foreign key on [Id] in table 'BaseEntity_Account' 103 ALTER TABLE [dbo].[BaseEntity_Account] 104 ADD CONSTRAINT [FK_Account_inherits_BaseEntity] 105 FOREIGN KEY ([Id]) 106 REFERENCES [dbo].[BaseEntity] 107 ([Id]) 108 ON DELETE CASCADE ON UPDATE NO ACTION; 109 GO 110 111 -- Creating foreign key on [Id] in table 'BaseEntity_Product' 112 ALTER TABLE [dbo].[BaseEntity_Product] 113 ADD CONSTRAINT [FK_Product_inherits_BaseEntity] 114 FOREIGN KEY ([Id]) 115 REFERENCES [dbo].[BaseEntity] 116 ([Id]) 117 ON DELETE CASCADE ON UPDATE NO ACTION; 118 GO 119 120 -- -------------------------------------------------- 121 -- Script has ended 122 -- -------------------------------------------------- 123
其次根据数据库生成表
根据数据库脚本,就可以知道最终建立了3张表。
最后,程序中调用,并监视执行的Sql
1、新增
程序调用
1 Account a = new Account() 2 { 3 Name = "US-1", 4 AppKeyId = "xxxxxxddsdfes", 5 AppSecretKey = "exdfesdKey", 6 MarketPlaceId = "jkhyed", 7 LastModifierId = 1, 8 LastModifyTime = DateTime.Now, 9 Version = 0, 10 CreateId = '1', 11 CreateTime = DateTime.Now, 12 13 }; 14 using (TestSystemContainer context = new TestSystemContainer()) 15 { 16 context.BaseEntity.Add(a); 17 context.SaveChanges(); 18 } 19
执行的Sql:
1 INSERT [dbo].[BaseEntity]([CreateId], [CreateTime], [LastModifierId], [LastModifyTime], [Version]) 2 VALUES (@0, @1, @2, @3, @4) 3 SELECT [Id] 4 FROM [dbo].[BaseEntity] 5 WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity() 6 7 8 -- @0: '49' (Type = Int32) 9 10 -- @1: '2018/7/17 星期二 14:46:28' (Type = DateTime2) 11 12 -- @2: '1' (Type = Int32) 13 14 -- @3: '2018/7/17 星期二 14:46:28' (Type = DateTime2) 15 16 -- @4: '0' (Type = Int32) 17 18 -- Executing at 2018/7/17 星期二 14:46:29 +08:00 19 20 INSERT [dbo].[BaseEntity_Account]([Name], [AppKeyId], [AppSecretKey], [MarketPlaceId], [Id]) 21 VALUES (@0, @1, @2, @3, @4) 22 23 -- @0: 'US-1' (Type = String, Size = -1) 24 25 -- @1: 'xxxxxxddsdfes' (Type = String, Size = -1) 26 27 -- @2: 'exdfesdKey' (Type = String, Size = -1) 28 29 -- @3: 'jkhyed' (Type = String, Size = -1) 30 31 -- @4: '3' (Type = Int32)
2、查询
程序调用
1 using (TestSystemContainer searchContext = new TestSystemContainer()) 2 { 3 var query = searchContext.BaseEntity.AsNoTracking(); 4 System.Diagnostics.Debug.WriteLine(query.ToString()); 5 List <BaseEntity> baseEnList= query.ToList(); 6 if (baseEnList != null) 7 { 8 foreach (var item in baseEnList) 9 { 10 Product product = item as Product; 11 if (product != null) 12 { 13 System.Diagnostics.Debug.Print("这是产品:"+product.Title); 14 } 15 16 else 17 { 18 Account account = item as Account; 19 if (account != null) 20 { 21 System.Diagnostics.Debug.Print("这是账号信息:"+ account.Name); 22 } 23 else 24 { 25 System.Diagnostics.Debug.Print("测试失败,查到的数据不是产品"); 26 } 27 } 28 } 29 30 } 31 else { 32 System.Diagnostics.Debug.Print("无数据"); 33 } 34 } 35
执行的Sql
1 SELECT 2 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN '0X' WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN '0X0X' ELSE '0X1X' END AS [C1], 3 [Extent1].[Id] AS [Id], 4 [Extent1].[CreateId] AS [CreateId], 5 [Extent1].[CreateTime] AS [CreateTime], 6 [Extent1].[LastModifierId] AS [LastModifierId], 7 [Extent1].[LastModifyTime] AS [LastModifyTime], 8 [Extent1].[Version] AS [Version], 9 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN [Project2].[Name] END AS [C2], 10 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN [Project2].[AppKeyId] END AS [C3], 11 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN [Project2].[AppSecretKey] END AS [C4], 12 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN [Project2].[MarketPlaceId] END AS [C5], 13 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) ELSE [Project1].[Code] END AS [C6], 14 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) ELSE [Project1].[Title] END AS [C7], 15 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) ELSE [Project1].[Description] END AS [C8], 16 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS decimal(18,0)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN CAST(NULL AS decimal(18,0)) ELSE [Project1].[Price] END AS [C9], 17 CASE WHEN (( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) AND ( NOT (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)))) THEN CAST(NULL AS decimal(18,0)) WHEN (([Project2].[C1] = 1) AND ([Project2].[C1] IS NOT NULL)) THEN CAST(NULL AS decimal(18,0)) ELSE [Project1].[Weight] END AS [C10] 18 FROM [dbo].[BaseEntity] AS [Extent1] 19 LEFT OUTER JOIN (SELECT 20 [Extent2].[Code] AS [Code], 21 [Extent2].[Title] AS [Title], 22 [Extent2].[Description] AS [Description], 23 [Extent2].[Price] AS [Price], 24 [Extent2].[Weight] AS [Weight], 25 [Extent2].[Id] AS [Id], 26 cast(1 as bit) AS [C1] 27 FROM [dbo].[BaseEntity_Product] AS [Extent2] ) AS [Project1] ON [Extent1].[Id] = [Project1].[Id] 28 LEFT OUTER JOIN (SELECT 29 [Extent3].[Name] AS [Name], 30 [Extent3].[AppKeyId] AS [AppKeyId], 31 [Extent3].[AppSecretKey] AS [AppSecretKey], 32 [Extent3].[MarketPlaceId] AS [MarketPlaceId], 33 [Extent3].[Id] AS [Id], 34 cast(1 as bit) AS [C1] 35 FROM [dbo].[BaseEntity_Account] AS [Extent3] ) AS [Project2] ON [Extent1].[Id] = [Project2].[Id] 36 37 38 39
总结
1、在新增或修改数据时需要操作两个表;
2、在查询时EF进行了多表的级联操作,并且在程序中需要进行转换,才能将父类型转换成实际的子类型。
所以不建议使用EF的继承方式建立实体间关系。