2014年11月25日 星期二

Entity Framework Code First 一對多關聯設定

兩個類別之間,一個包含集合導覽屬性,一個包含引用屬性,就會被當成一對多關系

主表
namespace ConsoleApplication1.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations.Schema;

    [Table("Topic")]
    public class Topic
    {
        public int TopicId { get; set; }

        public string Title { get; set; }

        public virtual ICollection<Reply> Reply { get; set; }
    }
}

明細表
外鍵的命名只有符合預設的規則,就會建立關系,規則如下
1. 目標類型索引的名稱
2. 目標類型名稱+目標類型主索引名稱
3. 導覽屬性名稱+目標類型主索引名稱
namespace ConsoleApplication1.Models
{
    using System.ComponentModel.DataAnnotations.Schema;

    [Table("Reply")]
    public class Reply
    {
        public int ReplyId { get; set; }

        public int TopicId { get; set; }
        // public int TopicTopicId { get; set; }
        // public int TheTopicTopicId { get; set; }

        public string Title { get; set; }
        
        public virtual Topic TheTopic { get; set; }
    }
}

若不是用預設規則的命名方式,可以透過ForeignKey這個Attribute設定
namespace ConsoleApplication1.Models
{
    using System.ComponentModel.DataAnnotations.Schema;

    [Table("Reply")]
    public class Reply
    {
        public int ReplyId { get; set; }

        [ForeignKey("TheTopic")]
        public int tid { get; set; }

        public string Title { get; set; }
        
        public virtual Topic TheTopic { get; set; }
    }
}

也可以設定在引用屬性上
namespace ConsoleApplication1.Models
{
    using System.ComponentModel.DataAnnotations.Schema;

    [Table("Reply")]
    public class Reply
    {
        public int ReplyId { get; set; }

        public int tid { get; set; }

        public string Title { get; set; }

        [ForeignKey("tid")]
        public virtual Topic TheTopic { get; set; }
    }
}

透過FluentAPI設定方式
namespace ConsoleApplication1.Models
{
    using System.Data.Entity;

    public class DemoContext : DbContext
    {
        public DbSet<Topic> Topic { get; set; }

        public DbSet<Reply> Reply { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Topic>()
                .HasMany(x => x.Reply)
                .WithRequired(x => x.TheTopic)
                .HasForeignKey(x => x.tid)
                .WillCascadeOnDelete(true);
        }
    }
}

資料表建立的樣子

關聯圖