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();
}
}
}
我试图与客户一起在许可证 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();
}
}
}