EF代码优先组合键关系

时间:2018-07-19 20:05:17

标签: entity-framework entity-framework-6 ef-code-first

我试图与客户在许可证表中创建复合密钥以及外键,但是当我运行EF命令update-database时,许可证表中将生成以下列。 / p>

enter image description here

我有下表

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在“许可证”表中充当PK和FK,但不知道如何生成那些名为Customer_Id和Customer_CompanyId`的额外列。 >

1 个答案:

答案 0 :(得分:1)

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

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

此外,EF还会从用于声明键的匿名类型表达式中得出Key列顺序,因此您无需显式设置它。

像这样:

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();
        }
    }
}