繁体   English   中英

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

[英]The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable.

这个问题可能看起来像其他类似问题的重复。 但我建议您仔细阅读问题,然后再决定是否与某些帖子重复????

我的数据库中有6个表,如下所示:

在此处输入图片说明

我已经在所有表中插入了一些记录。

现在,我正在尝试更新订单。

起初,我只是尝试如下更新订单:

CurrentOrder.UpdateOrder(Order);

OrderClient中的UpdateOrder方法如下所示:

public Order UpdateOrder(Order Order)
{
    IOrderRepository OrderRepository = _DataRepositoryFactory.GetDataRepository<IOrderRepository>();

    Order updatedEntity = null;

    if (Order.OrderId == 0)
    {
        updatedEntity = OrderRepository.Add(Order);
    }
    else
    {
        updatedEntity = OrderRepository.Update(Order);
    }

    return updatedEntity;

}

并在OrderRepository中:

protected override Order UpdateEntity(RateDifferenceContext entityContext, Order entity)
{
    return (from e in entityContext.OrderSet
            where e.OrderId == entity.OrderId
            select e).FirstOrDefault();
}

然后在DataRepositoryBase类中,我使用以下方法:

public T Update(T entity)
{
    using (U entityContext = new U())
    {
        T existingEntity = UpdateEntity(entityContext, entity);
        SimpleMapper.PropertyMap(entity, existingEntity);
        entityContext.SaveChanges();
        return existingEntity;
    }
}

这时我出现了一个错误,说:

违反多重性约束。 关系“ ...”的角色“ ...”具有多重性1或0..1

因此,我认为我需要删除所有相关表中特定于该顺序的记录。 因此,我尝试了以下代码:

using (var xaction = new TransactionScope())
{
    foreach (OrderItemDetail orderItemDetail in OrderItemDetailClient.GetAllOrderItemDetails().Where(x => x.OrderId == NewOrder.OrderId))
    {
        OrderItemDetailClient.DeleteOrderItemDetail(orderItemDetail);
    }

    foreach (Dispatch dispatch in DispatchClient.GetAllDispatches().Where(x => x.OrderId == NewOrder.OrderId))
    {
        foreach (DispatchItemDetail dispatchItemDetail in DispatchItemDetailClient.GetAllDispatchItemDetails().Where(x => x.InvoiceId == dispatch.InvoiceId))
        {
            DispatchItemDetailClient.DeleteDispatchItemDetail(dispatchItemDetail);
        }

        DispatchClient.DeleteDispatch(dispatch);
    }

    OrderClient.UpdateOrder(NewOrder);

    xaction.Complete();
}

现在,我收到另一个错误消息:

操作失败:由于一个或多个外键属性不可为空,因此无法更改该关系。 对关系进行更改时,相关的外键属性将设置为空值。 如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

我在最后一个代码块的以下提到的行中收到此错误:

DispatchClient.DeleteDispatch(dispatch);

您有两个不同的问题。 我们没有足够的细节来为您提供特定的修复程序,但是由于它们都是非常常见的EF“陷阱”,因此我相信逐步了解正在发生的事情非常有价值。

第一个错误:

违反多重性约束。 关系“ ...”的角色“ ...”具有多重性1或0..1

这意味着您的外键属性不匹配。 在EF中,您通常会遇到在模型中以多种方式表示相同的SQL关系的情况。

例如,您的Order类上可能有一个OrderItemDetails集合(使用OrderItemDetail.OrderId填充)。 您的OrderItemDetail可能还具有Order属性,该属性使用相同的外键填充。 如果这两个属性都标记为已更改,但新值不匹配,则EF不知道要保存到OrderItemdetail.OrderId字段中的新值。 在这种情况下,它将抛出此异常。 如果OrderItemDetail具有Order属性和OrderId属性,则会发生相同的问题。

为避免此问题,您必须非常小心修改哪些属性。 使用属性映射器可能很危险,因为它们会“意外地”修改错误的属性,并引起许多此类问题。 我们将需要查看SimpleMapper的工作方式或将该映射配置为真正的故障排除方法。

第二个错误:

操作失败:由于一个或多个外键属性不可为空,因此无法更改该关系。 对关系进行更改时,相关的外键属性将设置为空值。 如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

此错误通常表示您并未真正删除对象。 您正在从关系集合中删除对象,该关系集合仅将外键设置为null。

继续上面的示例,如果您调用myOrder.OrderItemDetails.Remove(detail)然后调用SaveChanges,您可能会认为它只会从数据库中删除OrderItemDetail记录,但这并不是您真正要的。 您从 myOrder 关联的订单商品详细信息列表中将其删除。 为此,EF生成了UPDATE语句,该语句将OrderId列设置为null。 如果没有来自DeleteDispatch方法的有关模型和代码的更多详细信息,很难确切地知道问题出在哪里,但是异常意味着它试图将外键属性设置为null并失败,因为它是不可为空的。

“修复”是直接从Context集合而不是相关的项目集合中删除项目。 即,而不是myOrder.OrderItemDetails.Remove,应调用context.OrderItemDetails.Remove。 这将删除真实记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM