EF抛出以下异常:
System.InvalidOperationException:参照完整性约束违规。依赖角色具有多个具有不同值的主体。
我有两个实体,StateProvince和Country:
public class StateProvince
{
public long Id { get; set; }
[StringLength(100)]
public string Name { get; set; }
public long CountryId { get; set; }
public Country Country { get; set; }
}
public class Country
{
public long Id { get; set; }
[StringLength(2)]
public string Code { get; set; }
public IEnumerable<StateProvince> StatesProvinces { get; set; }
}
和两个使用它们的实体:
public class Customer
{
public long Id { get; set; }
public long BillingStateProvinceId { get; set; }
[ForeignKey("Id")]
public StateProvince BillingStateProvince { get; set; }
public long BillingCountryId { get; set; }
[ForeignKey("Id")]
public Country BillingCountry { get; set; }
public long ShippingStateProvinceId { get; set; }
[ForeignKey("Id")]
public StateProvince ShippingStateProvince { get; set; }
public long ShippingCountryId { get; set; }
[ForeignKey("Id")]
public Country ShippingCountry { get; set; }
}
public class Vendor
{
public long Id { get; set; }
public long StateProvinceId { get; set; }
public StateProvince StateProvince { get; set; }
public long CountryId { get; set; }
public Country Country { get; set; }
}
在我的OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>()
.HasRequired(m => m.ShippingStateProvince)
.WithOptional().WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.ShippingCountry)
.WithOptional().WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.BillingStateProvince)
.WithOptional().WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.BillingCountry)
.WithOptional().WillCascadeOnDelete(false);
modelBuilder.Entity<Vendor>()
.HasRequired(m => m.StateProvince)
.WithOptional().WillCascadeOnDelete(false);
modelBuilder.Entity<Vendor>()
.HasRequired(m => m.Country)
.WithOptional().WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
最后,抛出异常的代码:
[TestMethod]
public void TestMethod1()
{
Db db = new Db();
#region Set/reset items
Country us = db.Countries.FirstOrDefault();
if (us == null)
{
us = new Country { Code = "US" };
db.Countries.Add(us);
db.SaveChanges();
}
long usId = us.Id;
List<StateProvince> states = db.StateProvinces.ToList();
StateProvince mass = states.Where(m => m.Name == "MA").FirstOrDefault();
StateProvince ct = states.Where(m => m.Name == "CT").FirstOrDefault();
if (mass == null)
{
mass = new StateProvince { Name = "MA", CountryId = usId };
ct = new StateProvince { Name = "CT", CountryId = usId };
db.StateProvinces.Add(mass);
db.StateProvinces.Add(ct);
db.SaveChanges();
}
long massId = mass.Id;
long ctId = ct.Id;
List<Customer> customersToRemove = db.Customers.ToList();
db.Customers.RemoveRange(customersToRemove);
db.SaveChanges();
#endregion
Customer customerToAdd = new Customer {
BillingStateProvinceId = massId,
ShippingStateProvinceId = ctId,
ShippingCountryId = usId,
BillingCountryId = usId,
BillingStateProvince = mass,
ShippingStateProvince = ct,
BillingCountry = us,
ShippingCountry = us
};
db.Customers.Add(customerToAdd);
try
{
//exception thrown here
db.SaveChanges();
}
catch (Exception e)
{
throw;
}
db.Dispose();
Db dbCheck = new Db();
Customer customer = dbCheck.Customers.Include(m => m.BillingStateProvince).Include(m => m.ShippingStateProvince).FirstOrDefault();
dbCheck.Dispose();
}
我怀疑问题是我没有正确使用[ForeignKey]属性,或者我在OnModelCreating中做错了什么。如果我在Customer实体中只有一个StateProvince和一个Country实体,我可以使它工作,但是,一旦我有两个,就无法弄明白。有什么帮助吗?
更广泛地说,是否有人有关于如何使用c#EF代码建模地址的博客/帖子/文章/教程的链接?我遇到this one,它使用[ComplexType]属性,问题是我无法封装其中的StateRegion和Country类。我目前的想法是将各个地址字段烘焙到每个类中,即MailingStreetAddress,BillingStreetAddress等。我想看看其他人如何处理地址以更好地理解如何自己做。
Per @Sam我是,我试图将属性更改为:
[ForeignKey("BillingStateProvinceId")]
每个属性。删除/重新创建数据库后,EF抛出了此错误:
Customer_BillingCountry_Source :: Multiplicity在关系'Customer_BillingCountry'中的角色'Customer_BillingCountry_Source'中无效。由于“从属角色”属性不是关键属性,因此从属角色的多重性的上限必须为“”。 Customer_BillingStateProvince_Source ::多重性在关系'Customer_BillingStateProvince'中的角色'Customer_BillingStateProvince_Source'中无效。由于Dependent Role属性不是关键属性,因此Dependent Role的多重性的上限必须为“”。 Customer_ShippingCountry_Source :: Multiplicity在关系'Customer_ShippingCountry'中的角色'Customer_ShippingCountry_Source'中无效。由于“从属角色”属性不是关键属性,因此从属角色的多重性的上限必须为“”。 Customer_ShippingStateProvince_Source ::多重性在关系'Customer_ShippingStateProvince'中的角色'Customer_ShippingStateProvince_Source'中无效。由于Dependent Role属性不是关键属性,因此Dependent Role的多重性的上限必须为“”。
Per @Steve Green,更改了我的StateRegion,Country实体和OnModelCreating,当我删除重新创建db时,它现在抛出此错误:
指定的架构无效。错误:未加载“StackOverflow.Customer_ShippingCountry”关系,因为“StackOverflow.Country”类型不可用。
我编辑的代码:
public class StateProvince
{
public long Id { get; set; }
[StringLength(100)]
public string Name { get; set; }
//new properties
public ICollection<Customer> Customers { get; set; }
public ICollection<Vendor> Vendors { get; set; }
public long CountryId { get; set; }
public Country Country { get; set; }
}
public class Country
{
public long Id { get; set; }
[StringLength(2)]
public string Code { get; set; }
//new properties
public ICollection<Customer> Customers { get; set; }
public ICollection<Vendor> Vendors { get; set; }
public IEnumerable<StateProvince> StatesProvinces { get; set; }
}
我的OnModel创建镜像他的:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>()
.HasRequired(m => m.ShippingStateProvince)
.WithMany(m => m.Customers)
.HasForeignKey(m => m.ShippingStateProvinceId);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.ShippingCountry)
.WithMany(m => m.Customers)
.HasForeignKey(m => m.ShippingCountryId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.BillingStateProvince)
.WithMany(m => m.Customers)
.HasForeignKey(m => m.BillingStateProvinceId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.BillingCountry)
.WithMany(m => m.Customers)
.HasForeignKey(m => m.BillingCountryId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Vendor>()
.HasRequired(m => m.StateProvince)
.WithMany(m => m.Vendors)
.HasForeignKey(m => m.StateProvinceId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Vendor>()
.HasRequired(m => m.Country)
.WithMany(m => m.Vendors)
.HasForeignKey(m => m.CountryId)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
答案 0 :(得分:1)
我相信你错误地使用了ForeignKeyAttribute。我通常这样做
[ForeignKey("BillingStateProvince")]
public long BillingStateProvinceId { get; set; }
public StateProvince BillingStateProvince { get; set; }
虽然我相信这也是有效的,
public long BillingStateProvinceId { get; set; }
[ForeignKey("BillingStateProvinceId")]
public StateProvince BillingStateProvince { get; set; }
'BillingStateProvinceId'是外键。当您执行[ForeignKey("Id")]
时,您指的是Customer.Id
,而不是StateProvince.Id
你也可能想用KeyAttribute
标记你的ID[Key]
public long Id { get; set; }
答案 1 :(得分:1)
由于你已经有了一个流畅的配置,你可以使用这样的东西并放弃注释:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>()
.HasRequired(m => m.StateProvince)
.WithMany()
.HasForeignKey(c => c.ShippingStateProvinceId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.Country)
.WithMany()
.HasForeignKey(c => c.ShippingCountryId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.StateProvince)
.WithMany()
.HasForeignKey(c => c.BillingStateProvinceId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Customer>()
.HasRequired(m => m.Country)
.WithMany()
.HasForeignKey(c => c.BillingCountryId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Vendor>()
.HasRequired(m => m.StateProvince)
.WithMany()
.HasForeignKey(c => c.StateProvinceId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Vendor>()
.HasRequired(m => m.StateProvince)
.WithMany()
.HasForeignKey(c => c.CountryId)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}