操作失败:无法更改关系,因为一个或多个外键属性不可为空

时间:2013-06-28 06:10:10

标签: c# entity-framework

这些是我的实体:

public class Currency : Exchange
{
     public List<CurrencyPrice> CurrencyPrice { get; set; }
}

public class CurrencyPrice : Price
{
    public int CurrencyId { get; set; }
    [ForeignKey("CurrencyId")]
    public Currency Currency { get; set; }
}

第一次将值插入数据库时​​,一切正常,但如果我更改数据库中的任何值并尝试插入或更新记录,我会收到此错误:

  

操作失败:无法更改关系,因为   一个或多个外键属性是不可为空的。当一个   改变了关系,相关的外键属性是   设置为空值。如果外键不支持空值,   必须定义新的关系,外键属性必须是   分配了另一个非空值,或者不相关的对象必须是   删除。

这是我的插入代码:

var currency =
    UnitOfWork.Exchange.Get(x => x is Currency && x.ExchangeType.Id == exchangeTypeId) as Currency;
if (currency != null)
{
    CurrencyPrice lastPriceValue = UnitOfWork.CurrencyPrice.Last(x => x.CurrencyId == currency.Id);
    if (lastPriceValue == null || lastPriceValue.Value != price)
    {
        currency.CurrencyPrice = new List<CurrencyPrice>
            {
                new CurrencyPrice {Id = Guid.NewGuid().ToString(), EntryDate = DateTime.Now, Value = price,CurrencyId = currency.Id,Currency = currency}
            };
    }
    else
    {
        lastPriceValue.EntryDate = DateTime.Now;
    }

    UnitOfWork.Commit();
}

我搜索了StackOverflow并找到了this。但我不明白我必须做什么。

2 个答案:

答案 0 :(得分:9)

我认为问题出在这个代码块中:

currency.CurrencyPrice = new List<CurrencyPrice>
{
    new CurrencyPrice {Id = Guid.NewGuid().ToString(), EntryDate = DateTime.Now, Value = price,CurrencyId = currency.Id,Currency = currency}
};

在此创建一个新的CurrencyPrice并将其分配给Currency,从而使之前分配给此CurrencyPrice的{​​{1}}对象孤立。此对象现在仍在数据库中,但没有父对象。因此,EntityFramework希望将此Currency上的父ID设置为CurrencyPrice,数据库会阻止该ID导致您引用的错误。我已在this answer中发布了有关此问题的更详细说明。

要防止这种情况,请在添加新数据库之前从数据库中删除旧的NULL。或者,由于CurrencyPrice对象似乎总是依赖于CurrencyPrice父对象,因此您可以考虑将此作为一种识别关系。我已经解释了如何使用EntityFramework 4 Model First在Implementing identifying relationships with EF4创建它们。我还没有使用Code First,但方法应该类似。

答案 1 :(得分:0)

在上下文中保存更改时出现相同的错误,并且未对实体或关系进行任何更改。

错误是因为某些实体具有ovveridden的GetHashCode()方法