2

我试图使用单个Address表来存储具有通用KeyId字段的系统中多个实体的地址。客户可以拥有多个地址,而供应商可以拥有多个地址。用于存储实体框架中许多实体(使用双重外键)地址的单个地址表

地址类:

public int Id { get; set; } 
public string Name { get; set; } 
public string Address1 { get; set; } 
public string Address2 { get; set; } 
public string City { get; set; } 
public string State { get; set; } 
public string Country { get; set; } 
public string ZipCode { get; set; } 
// These 2 fields make it so I can get all of the addresses for a single Customer or Vendor 
public string EntityType { get; set; } 
public int KeyId { get; set; } 

// Navigation properties 
public Customer Customer { get; set; } 
public Vendor Vendor { get; set; } 
public Location Location { get; set; } 

客户类:

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

// Navigation properties 
public IList<Address> Addresses { get; set; } 

供应商类:

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

// Navigation properties 
public IList<Address> Addresses { get; set; } 

的DbContext:

builder.Entity<Customer>() 
     .HasMany(c => c.Addresses) 
     .WithOne(a => a.Customer) 
     .HasForeignKey(a => a.KeyId); 

    builder.Entity<Vendor>() 
     .HasMany(v => v.Addresses) 
     .WithOne(a => a.Vendor) 
     .HasForeignKey(a => a.KeyId); 

当试图种子数据库(添加了几个地址沿供应商),我遇到了,上面写着以下内容的错误:

SQLEXCEPTION:MERGE语句冲突与FOREIGN KEY约束“FK_Address_Customer_KeyId”。数据库“MyDatabase”中出现冲突,表“dbo.Customer”,列'Id'。

我敢肯定这是因为参照完整性说有是与您试图在KeyId存储标识数据库中没有客户。

是否有任何可能的方式做这样的事情瓦特/ FluentAPI使用EF还是我在玩火?它只是似乎很疯狂不得不创建一个名为CustomerAddressVendorAddress,如果所有属性都是同一类。这几乎就像我需要指定EF不允许你做的双重外键。

附加说明:我想我会尝试,并设置一切SQL Management Studio中,然后在Visual Studio中添加数据库第一EF项目。我很好奇,看看它将如何创建模型和数据库上下文。

+0

我知道你在以后被称为复合型EF –

+0

@Chef_Code复杂类型是不是我想要的这里。它不适用于客户可以拥有多个地址且供应商可以拥有多个地址的一对多关系。 –

回答

1

它看起来像客户/供应商之间的映射VS地址类是不正确的。

你应该在地址表中不同ForeignKey的列指向不同父表[客户/供应商。

所以更改后的实体将是这样的:

地址:

public int Id { get; set; } 
public string Name { get; set; } 
public string Address1 { get; set; } 
public string Address2 { get; set; } 
public string City { get; set; } 
public string State { get; set; } 
public string Country { get; set; } 
public string ZipCode { get; set; } 
public int CustomerId { get; set; } 
public int VendorId { get; set; } 


// Navigation properties 
public Customer Customer { get; set; } 
public Vendor Vendor { get; set; } 

的DbContext

builder.Entity<Customer>() 
    .HasMany(c => c.Addresses) 
    .WithOne(a => a.Customer) 
    .HasForeignKey(a => a.CustomerId); 

builder.Entity<Vendor>() 
    .HasMany(v => v.Addresses) 
    .WithOne(a => a.Vendor) 
    .HasForeignKey(a => a.VendorId); 

希望这将有助于。

+0

我忘了这个选项。它不像我想要的那么干净。我真的很想使用KeyId。另外,我会假设在你的解决方案中CustomerId和VendorId都应该是空的? –

+0

是的,CustomerId和VendorId都是可以为空的字段。 没有2个独立的外键,EF不能映射正确的**客户:地址**或**供应商:地址**。 让我们假设一个场景,其中CustomerId 1&2的Customer表中有两条记录,Vendor Table中的VendorId 1&2有两条记录。 现在,如果要将所有这些记录映射到** Address **表,将总共​​4条记录与重复**'KeyId **,这将导致EF的问题,以决定哪个** KeyId **属于哪个客户/供应商 希望将清除您的疑问。感谢 –

+0

明白了...通常会有在地址表中调用类型的附加字段这将是客户或供应商,所以当我做一个选择,我会做address.where(A => a.Type ==“客户” && a.KeyId == 1)..但我假设没有办法告诉Entity Framework额外使用Type作为外键的一部分。像这样的人这样的东西让我想回到使用微型ORM,比如小巧玲珑和数据库优先的方法......似乎有更多的灵活性。 –