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

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

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

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

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

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

首先,我只是尝试按以下方式更新订单:

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。这将删除真实记录。

Java中的OrderByDecending(LINQ)等效项 - java

嗨,我是一名使用Java的C#开发人员。问题很简单:我如何才能将下面的c#代码写入Java并仍能正常工作:myCoffeeList.OrderByDescending(x => x.Name?.ToLower()?.Trim() == sender.Text.ToLower()?.Trim())); 我的sender.Text基本上是一个文本框。文本的…

LINQ RemoveAll代替循环 - c#

我有两个for循环,用于从列表中删除项目。我正在为这些循环寻找等效的LINQ语句for (Int32 i = points.Count - 1; i >= 0; i--) { for (Int32 j = touchingRects.Count - 1; j >= 0; j--) { if (touchingRects[j].HitTest(po…

Linq Any()的哪种使用效率更高? - c#

我有一个Linq查询,如下所示:return this._alarmObjectAlarmViolationList .Where(row => row.ObjectId == subId) .Where(row => row.AlarmInternalId == "WECO #1 (StdDev > UCL)") .W…

LINQ to SQL中的“无法识别的表达式节点数组索引linq”异常 - c#

这是我的LINQ,其中我将DateTime类型的字段与当前日期进行了比较- var srs = (from s in dcDistrict.ScheduledReportStatus where s.ReportConfigId.Equals(ConfigId) && s.Status.HasValue && s.Status…

LINQ to XML语法 - c#

我有一个简单的POCO类,用于保存从XML文件提取的数据,该XML文件定义如下:public class Demographics { public string FirstName { get; set; } public string LastName { get; set; } public string MiddleName { get; set; …