我试图与客户在许可证表中创建复合密钥以及外键,但是当我运行EF
命令update-database
时,许可证表中将生成以下列。 / p>
我有下表
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`的额外列。 >
答案 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();
}
}
}