1.什麼是Fluent API? EF中內嵌的約定將POCO類映射到表。但是,有時您無法或不想遵守這些約定,需要將實體映射到約定指示外的其他對象,所以Fluent API和註解都是一種方法,這兩種方法是用來配置EF在映射屬性時繞開約定。Code first fluent API最常訪問通過重寫OnM ...
1.什麼是Fluent API?
EF中內嵌的約定將POCO類映射到表。但是,有時您無法或不想遵守這些約定,需要將實體映射到約定指示外的其他對象,所以Fluent API和註解都是一種方法,這兩種方法是用來配置EF在映射屬性時繞開約定。Code first fluent API最常訪問通過重寫OnModelCreating方法在派生DbContext。
2.包含屬性和排除屬性
按照約定,數據模型中都包含一個getter和一個setter公共屬性。
2.1包含屬性
包含屬性官網解釋有點難以理解,我個人認為在OnModelCreating方法配置包含Blog模型,那麼當我們調用Blog模型讀寫數據時候就會從連接資料庫中讀寫對應Blog表。
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>(); }
2.2排除屬性
如果你不想往BlogMetadata上讀寫數據,可以使用數據批註或者fluent API從模型中排除該實體類型。
2.2.1數據批註
namespace EFModeling.DataAnnotations.IgnoreType { class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public BlogMetadata Metadata { get; set; } } //讀寫不映射該實體 [NotMapped] public class BlogMetadata { public DateTime LoadedFromDatabase { get; set; } } }
2.2.2Fluent API
namespace EFModeling.FluentAPI.IgnoreType { class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { //Ignore方法就是讀寫不映射該實體 modelBuilder.Ignore<BlogMetadata>(); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public BlogMetadata Metadata { get; set; } } public class BlogMetadata { public DateTime LoadedFromDatabase { get; set; } } }
3.主鍵
使用關係型資料庫時候,都會涉及到主鍵概念,用作每個實體實例的主要唯一標識符。
3.1數據批註
namespace EFModeling.DataAnnotations.KeySingle { class MyContext : DbContext { public DbSet<Car> Cars { get; set; } } class Car { //設置LicensePlate為主鍵 [Key] public string LicensePlate { get; set; } public string Make { get; set; } public string Model { get; set; } } }
3.2Fluent API
namespace EFModeling.FluentAPI.KeySingle { class MyContext : DbContext { public DbSet<Car> Cars { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Car>() //設置LicensePlate為主鍵 .HasKey(c => c.LicensePlate); } } class Car { public string LicensePlate { get; set; } public string Make { get; set; } public string Model { get; set; } } }
4.生成值
有三個可用於屬性的值生成模式:
●無值生成:沒有值生成意味著,需始終提供要保存到資料庫的有效值。必須先將有效的值賦予新的實體,再將這些新的實體添加到上下文中。
●在添加時生成值:在添加時生成值,意思是為新實體生成值。
●在添加或更新時生成值:在添加或更新時生成值,意味著在每次保存該記錄(插入或更新)時生成新值。
註:如果想在資料庫端添加或更新時自動生成值,我們可以通過觸發器和配置預設值等方法生成。例如,如果指定在添加或更新時要生成DateTime屬性,則必須設置生成值的方法。若要執行此操作,一種方法是配置GETDATE() 的預設值以生成新行的值,然後即可使用資料庫觸發器在更新過程中生成值,如下麵的示例觸發器所示:
USE [Blogging] GO /****** Object: Trigger [dbo].[Blog_Update_Trigger] Script Date: 2019/10/22 16:18:13 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER TRIGGER [dbo].[Blog_Update_Trigger] ON [dbo].[Blog] AFTER UPDATE AS BEGIN SET NOCOUNT ON; IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN; DECLARE @Id INT SELECT @Id = INSERTED.BlogId FROM INSERTED UPDATE dbo.Blog SET Updatetime = GETDATE() WHERE BlogId = @Id END
4.1數據批註
4.1.1無值生成
public class Blog { [DatabaseGenerated(DatabaseGeneratedOption.None)] public int BlogId { get; set; } public string Url { get; set; } }
4.1.2在添加時生成值
public class Blog { public int BlogId { get; set; } public string Url { get; set; } [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime Inserted { get; set; } }
4.1.3在添加或更新時生成值
public class Blog { public int BlogId { get; set; } public string Url { get; set; } [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime LastUpdated { get; set; } }
4.2Fluent API
4.2.1無值生成
modelBuilder.Entity<Blog>() .Property(b => b.BlogId) .ValueGeneratedNever();
4.2.2在添加時生成值
modelBuilder.Entity<Blog>() .Property(b => b.Inserted) .ValueGeneratedOnAdd();
4.2.3在添加或更新時生成值
modelBuilder.Entity<Blog>() .Property(b => b.LastUpdated) .ValueGeneratedOnAddOrUpdate();