(20)ASP.NET Core2.2 EF創建模型(必需屬性和可選屬性、最大長度、並發標記、陰影屬性)


1.必需和可選屬性

如果實體屬性可以包含null,則將其視為可選。如果屬性的有效值不可以包含null,則將其視為必需屬性。映射到關系數據庫架構時,必需的屬性將創建為不可為null的列,而可選屬性則創建為可以為null的列。

1.1約定

按照約定,.NET 類型可以包含null的屬性將配置為可選,而.NET類型不包含null的屬性將根據需要進行配置。例如,具有.net值類型(int、decimal、bool等)的所有屬性都是必需的,而具有可為null的.net值類型(int?、decimal?、bool?等)的所有屬性都是配置為可選。

1.2數據批注

可以按如下所示將"約定"可以為"可選"的屬性配置為"必需":

namespace EFModeling.DataAnnotations.Required
{
    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    }
    public class Blog
    {
        public int BlogId { get; set; }
        //加上這個批注,這個值就必需寫入
        [Required]
        public string Url { get; set; }
    }
}

1.3Fluent API

namespace EFModeling.FluentAPI.Required
{
    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>()
                .Property(b => b.Url)
                //這個方法表示必需寫入
                .IsRequired();
        }
    }
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    }
}

2.最大長度

配置最大長度可為數據存儲提供有關要對給定屬性使用的相應數據類型的提示。最大長度僅適用於數組數據類型,如string和byte[]。例如前端傳統數據長度遠大於限定的長度,則提示。

2.1約定

按照約定,應由數據庫提供程序為屬性選擇適當的數據類型,即數據庫字段設置長度多少,生產程序實體接受值時就限定長度多少。對於具有長度的屬性,數據庫提供程序通常將選擇允許最長數據長度的數據類型。例如,Microsoft SQL Server將對字符string屬性使用 nvarchar(max)(如果該列用作鍵,則會使用nvarchar(450))。

2.2數據批注

你可以使用數據批注為屬性配置最大長度。此示例面向SQL Server,因此使用數據類型 nvarchar(500)。

namespace EFModeling.DataAnnotations.MaxLength
{
    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    }
    public class Blog
    {
        public int BlogId { get; set; }
        //設置最大長度
        [MaxLength(500)]
        public string Url { get; set; }
    }
}

2.3Fluent API

namespace EFModeling.FluentAPI.MaxLength
{
    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>()
                .Property(b => b.Url)
                //設置最大長度
                .HasMaxLength(500);
        }
    }
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    }
}

3.並發標記

當我們發現生產環境某個實體字段經常處於並發當中,我們可以批注一下為並發字段。

3.1約定

按照約定,屬性永遠不會配置為並發標記。

3.2數據注釋

您可以使用數據批注將屬性配置為並發標記。

public class Person
{
   public int PersonId { get; set; }
    //並發標記
    [ConcurrencyCheck]
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

3.3Fluent API

您可以使用熟知的API將屬性配置為並發標記。

class MyContext : DbContext
{
    public DbSet<Person> People { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .Property(p => p.LastName)
            //並發標記
            .IsConcurrencyToken();
    }
}
public class Person
{
    public int PersonId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

4.時間戳/行版本

時間戳是一個屬性類型,在每次插入或更新行時,數據庫都會生成一個新值。此該屬性類型也被視為並發標記。這可以確保在你和其他人修改了行數據時你會收到異常信息。

4.1約定

按照約定,屬性永遠不會配置為時間戳。

4.2數據注釋

你可以使用數據批注將屬性配置為時間戳。

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    //設置時間戳
    [Timestamp]
    public byte[] Timestamp { get; set; }
}

4.3Fluent API

你可以使用熟知的API將屬性配置為時間戳。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(p => p.Timestamp)
            //設置時間戳
            .IsRowVersion();
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public byte[] Timestamp { get; set; }
}

5.陰影屬性

當數據庫中的數據不應在映射的實體類型上公開時,陰影屬性非常有用。它們最常用於外鍵屬性,其中兩個實體之間的關系由數據庫中的外鍵值表示,但使用實體類型之間的導航屬性在實體類型上管理關系,可以通過ChangeTracker API獲取和更改影子屬性值:

context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;

可以通過EF.Property靜態方法在LINQ查詢中引用影子屬性:

var blogs = context.Blogs.OrderBy(b => EF.Property<DateTime>(b, "LastUpdated"));

5.1約定

如果發現了關系,但在依賴實體類中找不到外鍵屬性,則可以按約定創建陰影屬性。在這種情況下,將引入陰影外鍵屬性。影子外鍵屬性將命名<navigation property name><principal key property name>為(指向主體實體的依賴實體上的導航用於命名)。如果主體鍵屬性名稱包含導航屬性的名稱,則該名稱將只是<principal key property name>。如果依賴實體上沒有導航屬性,則會在其位置使用主體類型名稱。
例如,下面的代碼列表將導致BlogId Post向實體引入陰影屬性。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    //陰影屬性
    public List<Post> Posts { get; set; }
}
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
     //陰影屬性
    public Blog Blog { get; set; }
}

5.2數據注釋

不能通過數據批注創建陰影屬性。

5.3Fluent API

你可以使用"熟知API"配置陰影屬性。一旦你調用了Property方法的字符串重載,就可以鏈接到其他屬性的任何配置調用。如果提供Property方法的名稱與現有屬性的名稱相匹配(一個陰影屬性或在實體類中定義的屬性),則代碼將配置該現有屬性,而不是引入新的陰影屬性。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            //創建陰影屬性
            .Property<DateTime>("LastUpdated");
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}


參考文獻:
必需和可選屬性
最大長度
並發標記
陰影屬性


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM