简体   繁体   中英

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

This question might look like a duplicate to other similar questions. But I suggest you to read the question till end and then decide if its a duplicate of some post or not?????

I have 6 tables in my database as follows:

在此处输入图片说明

I have some records already inserted in all tables.

Now, I am trying to update an Order.

At first, I just tried to Update the order as follows:

CurrentOrder.UpdateOrder(Order);

The UpdateOrder method in OrderClient looks like:

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;

}

And in OrderRepository:

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

And then in DataRepositoryBase class I am using the below method:

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

At this point I got an error saying:

Multiplicity constraint violated. The role '…' of the relationship '…' has multiplicity 1 or 0..1

So, I thought that I need to delete the records which are specific to this order in all the related tables. So, I tried the below code:

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();
}

Now, I get another error saying that :

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

I get this error on below mentioned line in the last code-block:

DispatchClient.DeleteDispatch(dispatch);

You have two different problems. We don't have enough details to give you a specific fix, but since these are both very common EF "gotchas" I believe it's valuable to walk through what's happening.

The first error:

Multiplicity constraint violated. The role '…' of the relationship '…' has multiplicity 1 or 0..1

This means your foreign key properties do not match. In EF, you often end up in situations where the same SQL relationship is represented multiple ways in your model.

For example, your Order class may have a collection of OrderItemDetails on it (which is populated using OrderItemDetail.OrderId). Your OrderItemDetail may also have an Order property on it, which is populated using the same foreign key. If both of these properties are marked as changed but the new values don't match, EF doesn't know what new value to save to the OrderItemdetail.OrderId field. In that situation it will throw this exception. The same problem can occur if OrderItemDetail has an Order property and an OrderId property.

To avoid this problem, you have to be very careful which properties you modify. Using property mappers can be dangerous because they can "accidentally" modify the wrong properties and cause lots of problems like this. We would need to see how SimpleMapper works or how that mapping is configured to really troubleshoot.

The second error:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

This error typically means that you are not really deleting an object. You are removing the object from a relationship collection, which just sets the foreign key to null.

Continuing with the above example, if you call myOrder.OrderItemDetails.Remove(detail) then call SaveChanges, you may think it will just delete the OrderItemDetail record from the database, but that's not really what you told it to do. You removed it from the list of order item details associated with myOrder. In order to accomplish this, EF generates an UPDATE statement which sets the OrderId column to null. Without more details on your model and code from your DeleteDispatch method it's hard to know exactly where the issue is, but the exception means it's trying to set that foreign key property to null and failing because it's non-nullable.

The "fix" is to remove items directly from the Context collection instead of the related items collection. Ie instead of myOrder.OrderItemDetails.Remove, you should call context.OrderItemDetails.Remove. This deletes the record for real.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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