Entity Splitting
前言
繼上一篇文章將兩個Entity對應到同一個Table,反之,使用Code First將多個Table對應到一個Entity也是可行的。
範例:
目前有一個Student如下,並且打算將Address,Zip欄位的資料存在另一個Table。
public class Student
{
public int Id { get; set; }
public int SerialNumber { get; set; }
public string Name { get; set; }
//Enum型別
public Gender Gender { get; set; }
public byte[] Photo { get; set; }
public string Address { get; set; }
public string Zip { get; set; }
}
要做到Entity Splitting,目前無法用Data Annotation,只能用Fluent API。
使用Map的方式來將欄位分成兩個Table,如下:
public class StudentConfiguration : EntityTypeConfiguration<Student>
{
public StudentConfiguration()
{
HasKey(x => x.Id);
Map(m =>
{
m.Properties(d => new { d.Name, d.SerialNumber, d.Photo, d.Gender });
m.ToTable("StudentInformation");
}
).Map(m =>
{
m.Properties(d => new { d.Address, d.Zip });
m.ToTable("StudentAddress");
});
}
}
產生的資料表如下:
說明:
1.這兩個Table共享一個Primary Key,且我Map的時候是先寫Map StudentInformation再 Map StudentAddress,所以StudentAddress會建立Foreign Key依賴於StudentInformation。
2.如果未將所有欄位Map完,Code First會將未Map的欄位存在原本的Table之中。
產生的SQL指令
Select
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent2].[SerialNumber] AS [SerialNumber],
[Extent2].[Name] AS [Name],
[Extent2].[Gender] AS [Gender],
[Extent2].[Photo] AS [Photo],
[Extent1].[Address] AS [Address],
[Extent1].[Zip] AS [Zip]
FROM [dbo].[StudentAddress] AS [Extent1]
INNER JOIN [dbo].[StudentInformation] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
WHERE N'Miles' = [Extent2].[Name]
從產生的指令可以看到Entity Framework會自動INNER JOIN StudentInformation。
Insert
using (var db = new Model1())
{
Student s = new Student()
{
Name="Miles",
Address = "Road 1",
SerialNumber = 22
};
db.Student.Add(s);
db.SaveChanges();
}
exec sp_executesql N'INSERT [dbo].[StudentInformation]([SerialNumber], [Name], [Gender], [Photo])
VALUES (@0, @1, @2, NULL)
SELECT [Id]
FROM [dbo].[StudentInformation]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()',N'@0 int,@1 nvarchar(max) ,@2 tinyint',@0=22,@1=N'Miles',@2=0
exec sp_executesql N'INSERT [dbo].[StudentAddress]([Id], [Address], [Zip])
VALUES (@0, @1, NULL)
',N'@0 int,@1 nvarchar(max) ',@0=1,@1=N'Road 1'
從產生的指令可以看到,Entity Framework先Insert原本的StudentInformation,Insert完後會將產生的Id再Insert到StudentAddress中,完成兩次Insert的指令。
Update
using (var db = new Model1())
{
var s = db.Student.FirstOrDefault();
s.Name = "Kevin";
s.Address = "Avenu";
db.SaveChanges();
}
exec sp_executesql N'UPDATE [dbo].[StudentInformation]
SET [Name] = @0
WHERE ([Id] = @1)
',N'@0 nvarchar(max) ,@1 int',@0=N'Kevin',@1=1
exec sp_executesql N'UPDATE [dbo].[StudentAddress]
SET [Address] = @0
WHERE ([Id] = @1)
',N'@0 nvarchar(max) ,@1 int',@0=N'Avenu',@1=1
如果修改的欄位只會動到一個Table則Entity Framework只會產生一次Update指令,Update該欄位的Table。 如果修改的欄位分散在兩個Table,則Entity Framework會產生兩筆Update指令。
Delete
Entity Framework對應這兩個Table的時候是沒有Cascade Delete的。
但是Entity Framework知道刪除的時候需要把兩個Table的資料同時刪除,所以會產生兩筆刪除指令
exec sp_executesql N'DELETE [dbo].[StudentAddress]
WHERE ([Id] = @0)',N'@0 int',@0=1
exec sp_executesql N'DELETE [dbo].[StudentAddress]
WHERE ([Id] = @0)',N'@0 int',@0=1
小結
Entity Splitting比較會用在已經現有資料庫下,又想將多個Table整理成一個Entity,就可以使用此方式將多個Table合併成一個Entity。
一天一分享,身體好健康。
該追究的不是過去的原因,而是現在的目的。