添加多个订单实体后,在上下文中尝试SaveChanges()时,我收到以下错误:
操作失败:无法更改关系,因为一个或多个外键属性不可为null。当对关系进行更改时,相关的外键属性为设置为空值。如果外键不支持空值,必须定义新关系,外键属性必须指定了另一个非null值,或者不相关的对象必须已删除。
现在我知道这个错误意味着什么,我已经在谷歌上搜索了很多。问题是,我不会删除任何内容或覆盖任何内容(据我所知)。
在从亚马逊导入订单时,我在主应用程序中遇到了这个错误,所以我将代码剥离到控制台应用程序中,试图缩小范围,但到目前为止运气不佳。
控制台应用程序现在正在做我能想到的最起码的事情来重新创建错误——只需创建两个测试订单并调用Save。现在有趣的是两个测试订单,而不是一个。如果我只添加一个订单并调用Save,我不会收到错误——只有当我在实体列表中添加了多个订单时才会出现错误。
(现在我可以在每次Add之后调用Save(),但由于有很多订单要导入,所以速度会慢一些。此外,我想弄清真相——它曾经起过作用)
我在想我最近对应用程序所做的更改可能会导致这种情况——有一个,但我很难想出它可能导致这种情况的方法。
以前,每个订单记录都与一个名为Payments的表有一个(可为null)关系。我从模型中删除了那个表(和关系),并创建了一个类似的表&称为收据的关系。(想法是每个订单都将有零个或一个收据实体与其关联)。
添加测试订单时没有收据(根据模型,收据是有效的——ReceiptId可以为null),我在任何地方都找不到旧Payments表的任何痕迹。
如果有办法找出这个错误抱怨的是哪种关系,这样我就可以进一步缩小范围了?
private static void Main(string[] args)
{
var unitOfWork = new UnitOfWork();
var orders = GetOrders(unitOfWork);
foreach (var order in orders)
{
unitOfWork.OrdersRepository.AddOrder(order);
}
unitOfWork.Save();
Console.WriteLine("Done.");
Console.ReadLine();
}
private static IEnumerable<Order> GetOrders(IUnitOfWork unitOfWork)
{
// Use defaults
var country = unitOfWork.CountriesRepository.GetCountryById(223);
var source = unitOfWork.OrderSourceRepository.GetSourceById("AMZ");
var impression = unitOfWork.PostageImpressionRepository.GetPostageImpressionById(1);
for (var i = 0; i < 2; i++)
{
yield return
new Order
{
Address1 = "Address 1",
Address2 = "Address 2",
Address3 = "Address 3",
Town = "Town ",
County = "County",
EMail = "test@test.com",
ExternalOrderRef = "Ref",
FullName = "Test Order " + i,
OrderDate = DateTime.Now,
OrderSource = source,
Postcode = "AA11AA",
Telephone = "0123456789",
ExternalStatus = "New",
Total = 1.23m,
Paid = true,
PaidDate = DateTime.Now,
ShippedDate = null,
Cancelled = false,
Country = country,
Receipt = null,
PostageImpression = impression,
SubTotal = 1.23m,
PostageCost = 0.00m
};
}
}
事实证明,我在实体对象上重写了Equals(),这混淆了实体框架。
请参阅此处了解更多信息:
http://axilis.hr/entity-framework-override-equals-problem
我通过升级到EF 6解决了这个问题。