EF Code First 复合键关系

EF Code First Composite Key Relation

我试图与客户一起在许可证 table 中创建组合键和外键,但是当我 运行 EF 命令 update-database 时,正在许可证 table.

中生成以下列

我有以下 tables

public class Company
{
   public int Id { get; set; }
   public string Name { get; set; }
   public virtual ICollection<Customer> Customers { get; set; }
}


 public class Customer
 {
     public int Id { get; set; }
     public string Name { get; set; }

     public int CompanyId { get; set; }
     public virtual Company Company { get; set; }

     public ICollection<License> Licenses{ get; set; }
  }


public class License
{
   public int Id { get; set; }
   public int Count { get; set; }

   public int CustomerId { get; set; }
   public virtual Customer Customer { get; set; }
}


public class MyDbContext : DbContext
{
    public MyDbContext() : base("TestConnection")
    {

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

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

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


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>()
            .HasKey(cust => new { cust.Id, cust.CompanyId })
            .Property(cust => cust.Id).HasColumnOrder(1)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<Customer>()
            .Property(cust => cust.CompanyId).HasColumnOrder(2);



        modelBuilder.Entity<License>()
           .HasKey(lic => new { lic.Id, lic.CustomerId })
           .Property(lic => lic.Id).HasColumnOrder(1)
           .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<License>()
            .Property(lic => lic.CustomerId).HasColumnOrder(2);



        base.OnModelCreating(modelBuilder);
    }
}

注意:我希望 CustomerId 在许可证 table 中充当 PK 和 FK,但不知道这些额外的列如何命名 Customer_Id 和 Customer_CompanyId` 生成。

几件事。客户有一个复合密钥,因此您需要在许可证上有两个 FK 属性。而且你需要将License.Customer和Customer.Licenses关联起来,否则可能是两个独立的关联。

此外,您应该 将父键放在子实体的 PK 索引中的第一位。这样相关的行存储在一起,PK索引也支持外键关系。否则,您确实需要两个单独的索引:例如 Customer(Id) 和 Customer(CompanyId)。如果您希望能够在没有公司的情况下查找 Id 上的客户,请在 Customer(id) 上添加索引。

此外,EF 将从您用于声明键的匿名类型表达式派生键列顺序,因此您无需显式设置它。

像这样:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ef62test
{
    class Program
    {

        public class Company
        {
            public int Id { get; set; }
        }
        public class Customer
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int CompanyId { get; set; }
            public virtual Company Company { get; set; }

            public ICollection<License> Licenses { get; set; }
        }


        public class License
        {
            public int Id { get; set; }
            public int Count { get; set; }

            public int CompanyId { get; set; }
            public int CustomerId { get; set; }
            public virtual Customer Customer { get; set; }
        }


        public class MyDbContext : DbContext
        {

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

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

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


            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<Customer>()
                    .HasKey(cust => new { cust.CompanyId, cust.Id })
                    .Property(cust => cust.Id)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);


                modelBuilder.Entity<License>()
                   .HasKey(lic => new { lic.CompanyId, lic.CustomerId, lic.Id })
                   .Property(lic => lic.Id)
                   .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

                modelBuilder.Entity<License>()
                    .HasRequired(l => l.Customer)
                    .WithMany(c => c.Licenses)
                    .HasForeignKey(l => new { l.CompanyId, l.CustomerId });

                base.OnModelCreating(modelBuilder);
            }
        }
        static void Main(string[] args)
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());

            using (var db = new MyDbContext())
            {
                db.Database.Log = s => Console.WriteLine(s);

                db.Database.Initialize(true);



                db.SaveChanges();
            }


            Console.WriteLine("Hit any key to exit.");
            Console.ReadKey();
        }
    }
}