天天看點

EntityFramework Core是否可以映射私有屬性呢?了解一下。

前言

最近幾天身體有點抱恙,說話都需要勇氣,痛哭。今天簡短的寫一點探索性的内容,僅供了解,感謝您的閱讀。

EF Core映射私有屬性

在EF 6.x系列中寫過一篇文章可以映射私有屬性,說明EF的靈活性以及可擴充性,那麼問題來了在EF Core是否同樣可以呢,我們來試試。

public class Blog         {             public int Id { get; set; }             private string Name { get; set; }             public string Url { get; set; }             public DateTime CreatedTime { get; set; }             public DateTime ModifiedTime { get; set; }             public byte Status { get; set; }             public bool IsDeleted { get; set; }         }      

如上代碼,我們将Name設定私有屬性,接下來我們利用EF Core提供給我們的APi來通路是否可以進行映射到資料庫表中呢?我們來嘗試一下。

public class BlogConfiguration : IEntityTypeConfiguration<Blog>         {             public void Configure(EntityTypeBuilder<Blog> builder)             {                 var nonPublicProperties = builder.Metadata.ClrType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);                 foreach (var p in nonPublicProperties)                 {                     builder.Property(p.Name).HasColumnType("VARCHAR(50)");                 }                 builder.Property(p => p.CreatedTime).HasColumnType("DATETIME").HasDefaultValueSql("GETDATE()");             }         }      
protected override void OnModelCreating(ModelBuilder modelBuilder)             {                 modelBuilder.ApplyConfiguration(new BlogConfiguration());                 base.OnModelCreating(modelBuilder);             }      

在EF Core中如若我們需要通路中繼資料,則需要借助于在映射配置中即如上builder中的Metadata屬性來通路,比如通路屬性、主鍵、外鍵、導航屬性皆可,接下來我們遷移看看。

EntityFramework Core是否可以映射私有屬性呢?了解一下。

通過遷移生成的SQL語句我們就可得出結論:在EF Core中映射私有屬性和EF 6.x如出一轍,隻不過使用方式略有不同罷了。

當然實際場景中,若屬性為私有,那就沒有映射到資料庫中的必要了,這裡隻是作為探讨。下面我們再來看看實際場景,比如上述中的Name屬性為計算屬性,那麼此時我們會進行如下映射:

public class BlogConfiguration : IEntityTypeConfiguration<Blog>         {             public void Configure(EntityTypeBuilder<Blog> builder)             {                 builder.Property(p => p.Name).IsRequired().HasComputedColumnSql("((N'cnblogs'+CONVERT([CHAR](8),[CreatedTime],(112)))+RIGHT(REPLICATE(N'0',(6))+CONVERT([NVARCHAR],[Id],(0)),(6)))");                 builder.Property(p => p.CreatedTime).HasColumnType("DATETIME").HasDefaultValueSql("GETDATE()");             }         }      

此時我們在控制台進行如下送出:

var context = new EFCoreDbContext();                 context.Add(new Blog()                 {                     IsDeleted = false,                     Status = 0,                     ModifiedTime = DateTime.Now,                     Url = "http://www.cnblogs.com/createmyself",                     Name = "2222"                 });                 var result = context.SaveChanges();      

因為我們将上述Name配置為計算屬性,但是此時Name屬性中的SET通路器是公共的,是以可能會有誤操作對其進行指派,當然即使手動指派,最終依然能正确送出,結果不受任何影響,隻能說這樣可讀性不太好,既然Name為計算屬性即資料庫自動為其賦了值,那麼我們為何不将SET通路器設定為私有的呢,保持其隻讀而不可設定呢,改造如下即可:

public string Name { get; private set; }      

 如上設定Name為私有即不能手動為其指派,那麼我們可以視為計算屬性或者傳參指派,如下:

private Blog() { }             public Blog(string name)             {                 Name = name;             }      

在EF Core中利用構造函數傳參,那麼必須顯式存在無參構造函數,否則抛出異常,你懂的。再進一步講,我們也可将Name屬性作為隻作為字段來通路,配置成如下即可。

public void Configure(EntityTypeBuilder<Blog> builder)             {                 var property = builder.Metadata.FindProperty(nameof(Blog.Name));                 property.SetPropertyAccessMode(PropertyAccessMode.Field);                 builder.Property(p => p.Name).HasColumnType("VARCHAR(50)");                 builder.Property(p => p.CreatedTime).HasColumnType("DATETIME").HasDefaultValueSql("GETDATE()");             }      

總結

本節稍微探讨了下EF Core中如何映射私有屬性,雖然沒有什麼實際作用,可作為了解。想必很多時候,我們都會将屬性GET或者SET通路器都設定為公共的,雖然簡便但可讀性并那麼強,是計算屬性、還是字段等等,都應顯式設定,這樣可讀性會更好。

所有的選擇不過是為了下一次選擇做準備