︿
Top

2016年3月2日 星期三

Entity Framework Code First: Entity Association and DB Migration

前言


最近在研讀 ASP.NET MVC 5 : 網站開發美學 4.6.3 / 4.6.4 / 4.8 時, 將書中範例作了一次演練整合, 包含以下內容;

  • 定義或變更欄位的資料庫型態
  • 加入欄位
  • 1 to 1 關聯
  • 1 to many 關聯
  • many to many 關聯
  • 資料庫移轉 (Database Migration)

在閱讀本文的同時, 可以參考 ASP.NET MVC 5 : 網站開發美學 書中的章節作對照.


過程

    • 1. 建立 Console 專案
    • 2. 加入 ADO.NET 實體資料模型 --> 空的 Code First 模型 (BlogModel)
    • 3. 進行 Initial 資料庫的建立

      • 加入 Blog.cs / BlogArticle.cs ( 1 : n )
        • public class Blog
        • {
        •     public int Id { get; set; }
        •     public Guid OwnerId { get; set; }
        •     public string Caption { get; set; }
        •     public DateTime DateCreated { get; set; }
        • }
        •  
        • public class BlogArticle
        • {
        •     public Guid Id { get; set; }
        •     public int BlogId { get; set; }
        •     public string Subject { get; set; }
        •     public string Body { get; set; }
        •     public DateTime DateCreated { get; set; }
        •     public DateTime DateModified { get; set; }
        • }

      • 修改 BlogModel.cs
        • public virtual DbSet<Blog> Blogs { get; set; }
        • public virtual DbSet<BlogArticle> BlogArticles { get; set; }
        •  
        • protected override void OnModelCreating(DbModelBuilder modelBuilder)
        • {
        •     var blogTable = modelBuilder.Entity<Blog>().ToTable("Blogs");
        •     var blogArticleTable = modelBuilder.Entity<BlogArticle>().ToTable("BlogArticles");
        •     blogTable.Property(c => c.Id).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.BlogId).IsRequired().HasColumnType("bigint");
        •   base.OnModelCreating(modelBuilder);
        • }
      • 加入 MyDbInitializer 類別 (in Program.cs)
        • class MyDbInitializer : IDatabaseInitializer<BlogModel>
        • {
        •     public void InitializeDatabase(BlogModel context)
        •     {
        •         //context.Database.Delete();
        •         context.Database.CreateIfNotExists();
        •     }
        • }
      • 修改 Program.cs
        • static void Main(string[] args)
        • {
        •     using (BlogModel context = new BlogModel() )
        •     {
        •         // 方式一:
        •         // context.Database.CreateIfNotExists();     //如果資料庫不存在, 就建立
        •         // 方式二: 透過 IDatabaseInitializer<T> 的實作
        •         Database.SetInitializer(new MyDbInitializer()); // set initializer
        •         context.Database.Initialize(true);  // run initializer, 這裡才會跑 BlogModel.OnModelCreating()
        •     }
        • }
      • 執行程式, 會產生第一版的 DB
      • 在 Package Manager Console 裡, 下達  PM> Enable-Migrations
        • 在方案總管, 可以看到 Migrations 資料夾的產生.

    • 4. 進行第2次資料庫移轉 (限制欄位長度)

      • 修改 BlogModel.cs
        • protected override void OnModelCreating(DbModelBuilder modelBuilder)
        • {
        •     var blogTable = modelBuilder.Entity<Blog>().ToTable("Blogs");
        •     var blogArticleTable = modelBuilder.Entity<BlogArticle>().ToTable("BlogArticles");
        •     blogTable.Property(c => c.Id).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.BlogId).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.Subject).HasMaxLength(250).IsRequired();
        •     blogArticleTable.Property(c => c.Body).HasMaxLength(4000).IsRequired();
        •    base.OnModelCreating(modelBuilder);
        • }
      • 在 Package Manager Console 裡, 下達  PM> Add-Migration AlterBlogArticle
          • 這裡的 Up() 是資料庫升級用的; Down() 是資料庫降級用的
      • 資料庫還沒有變喔 ...
      • 執行 PM> Update-Database
      • 終於更改資料庫格式了

    • 5. 進行第3次資料庫移轉 (加入欄位)  

      • BlogArticle.cs 加入一個 Language 屬性
        • public class BlogArticle
        • {
        •     public Guid Id { get; set; }
        •     public int BlogId { get; set; }
        •     public string Subject { get; set; }
        •     public string Body { get; set; }
        •     public DateTime DateCreated { get; set; }
        •     public DateTime DateModified { get; set; }
        •     public string Language { get; set; }
        • }
      • PM> Add-Migration AlterBlogArticle
      • 此時, Console 專案會自動建置
      • PM> Update-Database

    • 6. 進行第4次資料庫移轉 ( 加入一對無或一的關係 )

      • 加入 BlogInfo.cs
        • public class BlogInfo
        • {
        •     public Guid Id { get; set; }
        •     public string Author { get; set; }
        •     // 每 1 筆 BlogInfo, 會有 1 筆 Blog (也有可能是 0 筆, 由程式決定)
        •     public Blog Blog { get; set; }
        • }
      • 修改 Blog.cs
        • public class Blog
        • {
        •     public int Id { get; set; }
        •     public Guid OwnerId { get; set; }
        •     public string Caption { get; set; }
        •     public DateTime DateCreated { get; set; }
        •     // 每 1 筆 Blog, 會有 1 筆 BlogInfo
        •     public BlogInfo Info { get; set; }
        • }
      • 修改 BlogModel.cs
        • public virtual DbSet<BlogInfo> BlogInfos { get; set; }
        •  
        • protected override void OnModelCreating(DbModelBuilder modelBuilder)
        • {
        •     var blogTable = modelBuilder.Entity<Blog>().ToTable("Blogs");
        •     var blogArticleTable = modelBuilder.Entity<BlogArticle>().ToTable("BlogArticles");
        •     var blogInfoTable = modelBuilder.Entity<BlogInfo>().ToTable("BlogInfos");
        •     // ================================
        •     // 修改資料庫對應的 DataType
        •     // ================================
        •     blogTable.Property(c => c.Id).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.BlogId).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.Subject).HasMaxLength(250).IsRequired();
        •     blogArticleTable.Property(c => c.Body).HasMaxLength(4000).IsRequired();
        •     // ================================
        •     // 建立關聯性
        •     // ================================
        •     // PKEY
        •     blogTable.HasKey(c => c.Id);   
        •     // --------------------------------
        •     // BlogInfos vs. Blogs = 1 vs. 0 or 1
        •     // --------------------------------
        •     //blogTable.HasRequired(c => c.Info).WithOptional();
        •     //http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx
        •     blogInfoTable.HasOptional(c => c.Blog)         // blogInfo has blog -> Optional
        •                            .WithRequired(a => a.Info);       // blog has blogInfo -> Required

        •     base.OnModelCreating(modelBuilder);
        • }
      • PM> Add-Migration AlterOneToOneRelation
      • PM> Update-Database
      • 修改  Program.cs 的 MyDbInitializer 類別
        • class MyDbInitializer : IDatabaseInitializer<BlogModel>
        • {
        •  
        •     private void OneToZero(BlogModel context)
        •     {
        •         // ---------------------------------
        •         // 1 to 0 or 1
        •         // ---------------------------------
        •         Guid blogInfoId = Guid.NewGuid();
        •         context.BlogInfos.Add(new BlogInfo()
        •         {
        •             Id = blogInfoId,
        •             Author = "Judy",
        •             Blog = null
        •         });
        •         blogInfoId = Guid.NewGuid();
        •         context.BlogInfos.Add(new BlogInfo()
        •         {
        •             Id = blogInfoId,
        •             Author = "Jasper",
        •             Blog = new Blog() { Id = 1, Caption = "Travel Blog Site", OwnerId = Guid.NewGuid(), DateCreated = DateTime.Now }
        •         });
        •     }

        •     public void InitializeDatabase(BlogModel context)
        •     {
        •         //context.Database.Delete();
        •         context.Database.CreateIfNotExists();
        •         //以下放一些初始資料新增
        •         // ---------------------------------
        •         // 1 to 0 or 1
        •         // ---------------------------------
        •         this.OneToZero(context);

      •         context.SaveChanges();
      •     }
      • }
      • PM> Update-Database -TargetMigration:"AlterBlogArticle1"

    • 7. 進行第5次資料庫移轉 ( 加入一對一的關係 )

      • 修改 BlogModel.cs
        • public virtual DbSet<BlogInfo> BlogInfos { get; set; }

        • protected override void OnModelCreating(DbModelBuilder modelBuilder)
        • {
        •     var blogTable = modelBuilder.Entity<Blog>().ToTable("Blogs");
        •     var blogArticleTable = modelBuilder.Entity<BlogArticle>().ToTable("BlogArticles");
        •     var blogInfoTable = modelBuilder.Entity<BlogInfo>().ToTable("BlogInfos");
        •     // ================================
        •     // 修改資料庫對應的 DataType
        •     // ================================
        •     blogTable.Property(c => c.Id).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.BlogId).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.Subject).HasMaxLength(250).IsRequired();
        •     blogArticleTable.Property(c => c.Body).HasMaxLength(4000).IsRequired();
        •     // ================================
        •     // 建立關聯性
        •     // ================================
        •     // PKEY
        •     blogTable.HasKey(c => c.Id);
        •     blogInfoTable.HasKey(c => c.Id);

        •     //// --------------------------------
        •     //// BlogInfos vs. Blogs = 1 vs. 0 or 1
        •     //// --------------------------------
        •     ////blogTable.HasRequired(c => c.Info).WithOptional();
        •     //blogInfoTable.HasOptional(c => c.Blog)  // blogInfo has blog -> Optional
        •     //    .WithRequired(a => a.Info);         // blog has blogInfo -> Required

        •     // --------------------------------
        •     // BlogInfos vs. Blogs = 1 vs. 1
        •     // --------------------------------
        •     //blogTable.HasRequired(c => c.Info).WithRequiredPrincipal(c => c.Blog);
        •     blogInfoTable.HasRequired(c => c.Blog)      // blogInfo has blog -> Required
        •         .WithRequiredPrincipal(a => a.Info);    // blog has blogInfo -> Required

        •     base.OnModelCreating(modelBuilder);
        • }

      • PM> Add-Migration AlterOneToOneRelation2
      • PM> Update-Database
      • 修改  Program.cs 的 MyDbInitializer 類別
        •  
        • private void OneToOne(BlogModel context)
        • {
        •     // ---------------------------------
        •     // 1 to 1
        •     // ---------------------------------
        •     Guid blogInfoId = Guid.NewGuid();
        •     context.BlogInfos.Add(new BlogInfo()
        •     {
        •         Id = blogInfoId,
        •         Author = "Jasper",
        •         Blog = new Blog() { Id = 2, Caption = "Travel Blog Site2", OwnerId = Guid.NewGuid(), DateCreated = DateTime.Now }
        •     });
        • }
        •  
        • public void InitializeDatabase(BlogModel context)
        • {
        •     //context.Database.Delete();
        •     context.Database.CreateIfNotExists();
        •     //以下放一些初始資料新增
        •     //// ---------------------------------
        •     //// 1 to 0 or 1
        •     //// ---------------------------------
        •     //this.OneToZero(context);
        •    
        •     // ---------------------------------
        •     // 1 to 1
        •     // ---------------------------------
        •     this.OneToOne(context);

        •     context.SaveChanges();
        • }
      • 執行程式

    • 8. 進行第6次資料庫移轉 ( 加入一對多的關係 )

      • 修改 Blog.cs
        • public class Blog
        • {
        •     public int Id { get; set; }
        •     public Guid OwnerId { get; set; }
        •     public string Caption { get; set; }
        •     public DateTime DateCreated { get; set; }
        •     // 每 1 筆 Blog, 會有 1 筆 BlogInfo
        •     public BlogInfo Info { get; set; }
        •     // 每一個 Blog Site, 會有多篇文章
        •     public ICollection<BlogArticle> Articles { get; set; }
        • }
      • 修改 BlogArticle.cs
        • public class BlogArticle
        • {
        •     public Guid Id { get; set; }
        •     public int BlogId { get; set; }
        •     public string Subject { get; set; }
        •     public string Body { get; set; }
        •     public DateTime DateCreated { get; set; }
        •     public DateTime DateModified { get; set; }
        •     public string Language { get; set; }
        •     // 每一篇文章都屬於一個 Blog Site
        •     public Blog Blog { get; set; }
        • }
      • 修改 BlogModel.cs
        • protected override void OnModelCreating(DbModelBuilder modelBuilder)
        • {
        •     var blogTable = modelBuilder.Entity<Blog>().ToTable("Blogs");
        •     var blogArticleTable = modelBuilder.Entity<BlogArticle>().ToTable("BlogArticles");
        •     var blogInfoTable = modelBuilder.Entity<BlogInfo>().ToTable("BlogInfos");
        •     // ================================
        •     // 修改資料庫對應的 DataType
        •     // ================================
        •     blogTable.Property(c => c.Id).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.BlogId).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.Subject).HasMaxLength(250).IsRequired();
        •     blogArticleTable.Property(c => c.Body).HasMaxLength(4000).IsRequired();
        •     // ================================
        •     // 建立關聯性
        •     // ================================
        •     // PKEY
        •     blogTable.HasKey(c => c.Id);
        •     blogInfoTable.HasKey(c => c.Id);

        •     //// --------------------------------
        •     //// BlogInfos vs. Blogs = 1 vs. 0 or 1
        •     //// --------------------------------
        •     ////blogTable.HasRequired(c => c.Info).WithOptional();
        •     //blogInfoTable.HasOptional(c => c.Blog)  // blogInfo has blog -> Optional
        •     //    .WithRequired(a => a.Info);         // blog has blogInfo -> Required

        •     // --------------------------------
        •     // BlogInfos vs. Blogs = 1 vs. 1
        •     // --------------------------------
        •     //blogTable.HasRequired(c => c.Info).WithRequiredPrincipal(c => c.Blog);
        •     blogInfoTable.HasRequired(c => c.Blog)      // blogInfo has blog -> Required
        •         .WithRequiredPrincipal(a => a.Info);    // blog has blogInfo -> Required

        •     // --------------------------------
        •     // Blogs vs. BlogArticles = 1 vs. n
        •     // --------------------------------
        •     blogTable.HasMany(c => c.Articles)      // Blog has many Articles -> Required
        •         .WithRequired(a => a.Blog);         // Articles has Blog -> Required

        •     base.OnModelCreating(modelBuilder);
        • }
      • PM> Add-Migration AlterOneToManyRelation
      • PM> Update-Database
      • 修改  Program.cs 的 MyDbInitializer 類別
        • private void OneToMany(BlogModel context)
        • {
        •     // ---------------------------------
        •     // 1 to n
        •     // ---------------------------------
        •     Guid blogInfoId = Guid.NewGuid();
        •     context.BlogInfos.Add(new BlogInfo()
        •     {
        •         Id = blogInfoId,
        •         Author = "Jasper",
        •         Blog = new Blog()
        •         {
        •             Id = 3,
        •             Caption = "Travel Blog Site3",
        •             OwnerId = Guid.NewGuid(),
        •             DateCreated = DateTime.Now,
        •             Articles = new List<BlogArticle>()
        •             {
        •                 new BlogArticle() { Id = Guid.NewGuid(), BlogId = 3, Subject = "Japan", Body = "Tokyo", Language="中文", DateCreated = DateTime.Now, DateModified = DateTime.Now },
        •                 new BlogArticle() { Id = Guid.NewGuid(), BlogId = 3, Subject = "Japan", Body = "Kyoto", Language="中文", DateCreated = DateTime.Now, DateModified = DateTime.Now }
        •             }
        •         }
        •     });
        • }

        • public void InitializeDatabase(BlogModel context)
        • {
        •     //context.Database.Delete();
        •     context.Database.CreateIfNotExists();
        •     //以下放一些初始資料新增

        •     //// ---------------------------------
        •     //// 1 to 0 or 1
        •     //// ---------------------------------
        •     //this.OneToZero(context);

        •     //// ---------------------------------
        •     //// 1 to 1
        •     //// ---------------------------------
        •     //this.OneToOne(context);

        •     // ---------------------------------
        •     // 1 to n
        •     // ---------------------------------
        •     this.OneToMany(context);

        •     context.SaveChanges();
        • }
      • 執行程式

    • 9. 進行第7次資料庫移轉 ( 加入多對多的關係 )

      • 加入 BlogFile.cs 
      • 1個檔案 (BlogFile), 可以被篇文章 (BlogArticle) 使用; 1篇文章 (BlogArticle), 可以包含多個檔案 (BlogFile)
        • public class BlogFile
        • {
        •     public Guid Id { get; set; }
        •     public string Name { get; set; }
        •     //1個檔案, 可以被篇文章 (article) 使用
        •     public ICollection<BlogArticle> Articles { get; set; }
        • }
      • 修改 BlogArticle.cs
        • public class BlogArticle
        • {
        •     public Guid Id { get; set; }
        •     public int BlogId { get; set; }
        •     public string Subject { get; set; }
        •     public string Body { get; set; }
        •     public DateTime DateCreated { get; set; }
        •     public DateTime DateModified { get; set; }
        •     public string Language { get; set; }
        •     // 每一篇文章都屬於一個 Blog Site
        •     public Blog Blog { get; set; }
        •     //1篇文章, 可以包含多個檔案
        •     public ICollection<BlogFile> Files { get; set; }
        • }
      • 修改 BlogModel.cs
        • public virtual DbSet<BlogFile> BlogFiles { get; set; }
        • protected override void OnModelCreating(DbModelBuilder modelBuilder)
        • {
        •     var blogTable = modelBuilder.Entity<Blog>().ToTable("Blogs");
        •     var blogArticleTable = modelBuilder.Entity<BlogArticle>().ToTable("BlogArticles");
        •     var blogInfoTable = modelBuilder.Entity<BlogInfo>().ToTable("BlogInfos");
        •     var blogFileTable = modelBuilder.Entity<BlogFile>().ToTable("BlogFiles");
        •     // ================================
        •     // 修改資料庫對應的 DataType
        •     // ================================
        •     blogTable.Property(c => c.Id).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.BlogId).IsRequired().HasColumnType("bigint");
        •     blogArticleTable.Property(c => c.Subject).HasMaxLength(250).IsRequired();
        •     blogArticleTable.Property(c => c.Body).HasMaxLength(4000).IsRequired();

        •     // ================================
        •     // 建立關聯性
        •     // ================================
        •     // PKEY
        •     blogTable.HasKey(c => c.Id);
        •     blogInfoTable.HasKey(c => c.Id);
        •     blogFileTable.HasKey(c => c.Id);

        •     //// --------------------------------
        •     //// BlogInfos vs. Blogs = 1 vs. 0 or 1
        •     //// --------------------------------
        •     ////blogTable.HasRequired(c => c.Info).WithOptional();
        •     //blogInfoTable.HasOptional(c => c.Blog)  // blogInfo has blog -> Optional
        •     //    .WithRequired(a => a.Info);         // blog has blogInfo -> Required

        •     // --------------------------------
        •     // BlogInfos vs. Blogs = 1 vs. 1
        •     // --------------------------------
        •     //blogTable.HasRequired(c => c.Info).WithRequiredPrincipal(c => c.Blog);
        •     blogInfoTable.HasRequired(c => c.Blog)      // blogInfo has blog -> Required
        •         .WithRequiredPrincipal(a => a.Info);    // blog has blogInfo -> Required

        •     // --------------------------------
        •     // Blogs vs. BlogArticles = 1 vs. n
        •     // --------------------------------
        •     blogTable.HasMany(c => c.Articles)      // Blog has many Articles -> Required
        •         .WithRequired(a => a.Blog);         // Articles has Blog -> Required

        •     // --------------------------------
        •     // BlogArticles vs. BlogFiles = m vs. n
        •     // --------------------------------
        •     // 多對多: 在關聯式資料庫不存在, 會多產生一個 Table, 內含雙方的 PKey, 以造成 2 個 一對多 的關係
        •     blogArticleTable.HasMany(c => c.Files)      // BlogArticle has many BlogFile -> Required
        •         .WithMany(a => a.Articles)         // BlogFile has many BlogAritcle -> Required
        •         .Map
        •         ( m =>
        •             {
        •                 m.ToTable("BlogArticlesFiles");
        •                 m.MapLeftKey("BlogArticlesId");
        •                 m.MapRightKey("BlogFilesId");
        •             }
        •         );

        •     base.OnModelCreating(modelBuilder);
        • }
      • PM> Add-Migration AlterManyToManyRelation
      • PM> Update-Database
        • BlogArticlesFiles 出現了
      • 修改  Program.cs 的 MyDbInitializer 類別
        • private void ManyToMany(BlogModel context)
        • {
        •     // ---------------------------------
        •     // m to n
        •     // ---------------------------------
        •     Guid blogInfoId = Guid.NewGuid();
        •     //建立多個檔案
        •     BlogFile file1 = new BlogFile() { Id = Guid.NewGuid(), Name = "BMP檔" };
        •     BlogFile file2 = new BlogFile() { Id = Guid.NewGuid(), Name = "JPG檔" };
        •     BlogFile file3 = new BlogFile() { Id = Guid.NewGuid(), Name = "TXT檔" };
        •     context.BlogInfos.Add(new BlogInfo()
        •     {
        •         Id = blogInfoId,
        •         Author = "Jasper",
        •         Blog = new Blog()
        •         {
        •             Id = 4,
        •             Caption = "Travel Blog Site4",
        •             OwnerId = Guid.NewGuid(),
        •             DateCreated = DateTime.Now,
        •             Articles = new List<BlogArticle>()
        •             {
        •                 new BlogArticle() { Id = Guid.NewGuid(), BlogId = 4, Subject = "Taiwan", Body = "Taipei", Language="中文", DateCreated = DateTime.Now, DateModified = DateTime.Now,
        •                         Files = new List<BlogFile>(){ file1, file2 }  },
        •                 new BlogArticle() { Id = Guid.NewGuid(), BlogId = 4, Subject = "Taiwan", Body = "Tainan", Language="中文", DateCreated = DateTime.Now, DateModified = DateTime.Now,
        •                         Files = new List<BlogFile>(){ file2, file3 }  },
        •                 new BlogArticle() { Id = Guid.NewGuid(), BlogId = 4, Subject = "Taiwan", Body = "Taoyuan", Language="中文", DateCreated = DateTime.Now, DateModified = DateTime.Now,
        •                         Files = new List<BlogFile>(){ file3, file1 }  }
        •             }
        •         }
        •     });
        • }

        • public void InitializeDatabase(BlogModel context)
        • {
        •     //context.Database.Delete();
        •     context.Database.CreateIfNotExists();

        •     //以下放一些初始資料新增

        •     //// ---------------------------------
        •     //// 1 to 0 or 1
        •     //// ---------------------------------
        •     //this.OneToZero(context);

        •     //// ---------------------------------
        •     //// 1 to 1
        •     //// ---------------------------------
        •     //this.OneToOne(context);

        •     //// ---------------------------------
        •     //// 1 to n
        •     //// ---------------------------------
        •     //this.OneToMany(context);

        •     // ---------------------------------
        •     // m to n
        •     // ---------------------------------
        •     this.ManyToMany(context);

        •     context.SaveChanges();
        • }
      • 執行程式


    參考文件

    • Entity Framework Tutorial: Entity Relationships
      • 介紹 Entity 之間的關聯性
        • 1 to 1
        • 1 to many
        • many to many
      • Code Project: Create Primary Key using Entity Framework Code First
        • 在 Code First 的狀況下, 共有以下3種方式, 可以設定主鍵 (Primary Key):
          • Convention: Property with name "Id" or property with name {class name} + "Id" (both are case insensitive)
          • Data Annotation: [Key] attribute
          • Fluent API: Entity<T>.HasKey(p => p.PropertyName) function
        • 以下為複合鍵 (Composite Key) 的設定範例     
      // Data Annotation Attribute 
        public class Passport
          {
             [Key]
             [Column(Order = 10)]
             public string PassportNumber { getset; }

             [Key]
             [Column(Order = 20)]
             public string CountryCode { getset; } 

          }

      // Fluent API
      modelBuilder.Entity<Passport>().HasKey(s => new { s.PassportNumber, s.CountryCode});










      沒有留言:

      張貼留言