[C#.NET][Entity Framework] Code First 使用 Attribute / Fluent 來設定關聯屬性

[C#.NET][Entity Framework] Code First 使用 Attribute / Fluent 來設定關聯屬性

續上篇,http://www.dotblogs.com.tw/yc421206/archive/2014/03/15/144403.aspx

當 EF 慣用預設行為,已經沒有辦法滿足的時候,可以使用 Attribute 或 Fluent 應用程式來開發

 

System.ComponentModel.DataAnnotations 命名空間,有一些可以套用在 EF 的 Attribute

KeyAttribute 表示唯一識別實體的一個或多個屬性
MaxLengthAttribute 指定屬性中所允許之陣列或字串資料的最大長度
MinLengthAttribute 指定屬性中所允許之陣列或字串資料的最小長度

RequiredAttribute

必填欄位
StringLengthAttribute 指定資料欄位中允許的最小和最大字元長度
   

 

System.ComponentModel.DataAnnotations.Schema 命名空間,這很明顯就是要給 SQL 用的了,就不再列表了

 

有關 Attribute 可以參考以下連結

http://msdn.microsoft.com/zh-tw/data/jj591583#Relationships

 

Attribute很好用,可以直接跟 ASP.NET MVC 做驗証,在閱讀上也是相當直覺,不過…


還是會有一些情況是無法透過 Attribute 來處理,這時候就必須要用 Fluent 來開發,我們可能會用到以下方法

  1. EntityTypeConfiguration<TEntityType> 方法
  2. RequiredNavigationPropertyConfiguration<TEntityType, TTargetEntityType> 方法
  3. DependentNavigationPropertyConfiguration<TDependentEntityType>.WillCascadeOnDelete 方法

 

Fluent 可以寫在兩個地方

  1. 衍生 DbContext 類別的 OnModelCreating 方法裡
  2. 實作 EntityTypeConfiguration<TEntity>,提供給 OnModelCreating 調用或是套用在衍生 DbContext 類別上,如 http://www.dotblogs.com.tw/yc421206/archive/2014/03/15/144399.aspx

public class SystemDbContext : DbContext
{
…
}

 


{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Configurations.Add(new CategoryConfiguration());
    }
}

一對多對應寫法


{
    public CategoryConfiguration()
    {
        // Primary Key
        this.HasKey(t => t.Id);

        // Properties
        this.Property(t => t.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(t => t.Name).IsRequired()
            .HasMaxLength(100);

        // Table & Column Mappings
        this.ToTable("Category");
        this.Property(t => t.Id).HasColumnName("Id");
        this.Property(t => t.Name).HasColumnName("Name");
    }
}

{
    public ProductConfiguration()
    {
        // Primary Key
        this.HasKey(t => t.Id);

        // Properties
        this.Property(t => t.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(t => t.Name).IsRequired()
            .HasMaxLength(100);
        this.Property(t => t.UnitPrice).HasPrecision(10, 2);

        // Table & Column Mappings
        this.ToTable("Product");
  
        // Relationships
        this.HasRequired(t => t.Category)
            .WithMany(t => t.Products)
            .HasForeignKey(t => t.CategoryId)
            .WillCascadeOnDelete(false);
    }
}


在 OnModelCreating 裡調用

 


{
    public DbSet<Category> Categories { get; set; }

    public DbSet<Product> Products { get; set; }

    public SystemDbContext()
        : base("localdb")
    {
        Database.SetInitializer(new DropCreateDatabaseAlways<SystemDbContext>());
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new CategoryConfiguration());
        modelBuilder.Configurations.Add(new ProductConfiguration());
    }
}

 

 


一對一關聯互查

我想要在 Employee 與 Identity 能夠用物件


{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual Identity Identity { get; set; }
}

public class Identity
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    public string Account { get; set; }

    public string Password { get; set; }

    public virtual Employee Employee { get; set; }
}

 

上面的寫法 EF 預設不支援,我們可以透過 Fluent 來關聯它們


{
    modelBuilder.Entity<Employee>();
    modelBuilder.Entity<Identity>()
                   .HasOptional(q => q.Employee)
                   .WithOptionalPrincipal(t => t.Identity)
                   .Map(t => t.MapKey("IdentityId"));
}

 

產生的 Schema 如下圖:

image

 

 

雖然資料表仍是相同,就物件的操作來講的確能達到互相查詢的效果

 

這裡還有更多的Fluent

http://msdn.microsoft.com/zh-tw/data/jj591617.aspx

http://msdn.microsoft.com/zh-tw/data/hh134698.aspx


文章出自:http://www.dotblogs.com.tw/yc421206/archive/2014/03/18/144424.aspx

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo