无法更改关系,因为一个或多个外键属性不可为空 [英] The relationship could not be changed because one or more of the foreign-key properties is non-nullable

查看:188
本文介绍了无法更改关系,因为一个或多个外键属性不可为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在GetById()上获取此错误,然后将子实体的集合设置为来自MVC视图的新列表。

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

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.

我不太明白这一行:


关系无法更改
,因为一个或多个外键
属性不可为空。

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

为什么要更改2个实体之间的关系?它应该在整个应用程序的整个生命周期内保持不变。

Why would I change the relationship between 2 entities? It should remain the same throughout the lifetime of the whole application.

发生异常的代码是将集合中的修改后的子类简单地分配给现有的父类。这将有助于消除儿童课程,增加新课程和修改课程。我会以为实体框架处理这个。

The code the exception occurs on is simple assigning modified child classes in a collection to the existing parent class. This would hopefully cater for removal of child classes, addition of new ones and modifications. I would have thought Entity Framework handles this.

代码行可以被提炼为:

var thisParent = _repo.GetById(1);
thisParent.ChildItems = modifiedParent.ChildItems();
_repo.Save();


推荐答案

您应该删除旧的子项目 thisParent.ChildItems 一个一个地手动。实体框架不适合你。它最终无法决定你想要处理的旧的孩子物品 - 如果你想把它们丢弃,或者你想保留并分配给其他父母实体。你必须告诉实体框架你的决定。但是,由于子实体不能独立生活,而是在数据库中引用任何父类(由于外键约束),所以您必须做出这两个决定之一。这基本上是异常说的。

You should delete old child items thisParent.ChildItems one by one manually. Entity Framework doesn't do that for you. It finally cannot decide what you want to do with the old child items - if you want to throw them away or if you want to keep and assign them to other parent entities. You must tell Entity Framework your decision. But one of these two decisions you HAVE to make since the child entities cannot live alone without a reference to any parent in the database (due to the foreign key constraint). That's basically what the exception says.

修改

如果可以添加子项目,并删除:

What I would do if child items could be added, updated and deleted:

public void UpdateEntity(ParentItem parent)
{
    // Load original parent including the child item collection
    var originalParent = _dbContext.ParentItems
        .Where(p => p.ID == parent.ID)
        .Include(p => p.ChildItems)
        .SingleOrDefault();
    // We assume that the parent is still in the DB and don't check for null

    // Update scalar properties of parent,
    // can be omitted if we don't expect changes of the scalar properties
    var parentEntry = _dbContext.Entry(originalParent);
    parentEntry.CurrentValues.SetValues(parent);

    foreach (var childItem in parent.ChildItems)
    {
        var originalChildItem = originalParent.ChildItems
            .Where(c => c.ID == childItem.ID && c.ID != 0)
            .SingleOrDefault();
        // Is original child item with same ID in DB?
        if (originalChildItem != null)
        {
            // Yes -> Update scalar properties of child item
            var childEntry = _dbContext.Entry(originalChildItem);
            childEntry.CurrentValues.SetValues(childItem);
        }
        else
        {
            // No -> It's a new child item -> Insert
            childItem.ID = 0;
            originalParent.ChildItems.Add(childItem);
        }
    }

    // Don't consider the child items we have just added above.
    // (We need to make a copy of the list by using .ToList() because
    // _dbContext.ChildItems.Remove in this loop does not only delete
    // from the context but also from the child collection. Without making
    // the copy we would modify the collection we are just interating
    // through - which is forbidden and would lead to an exception.)
    foreach (var originalChildItem in
                 originalParent.ChildItems.Where(c => c.ID != 0).ToList())
    {
        // Are there child items in the DB which are NOT in the
        // new child item collection anymore?
        if (!parent.ChildItems.Any(c => c.ID == originalChildItem.ID))
            // Yes -> It's a deleted child item -> Delete
            _dbContext.ChildItems.Remove(originalChildItem);
    }

    _dbContext.SaveChanges();
}

注意:这没有测试。假设子项目集合的类型为 ICollection 。 (我通常有 IList ,然后代码看起来有点其他)。我也删除了所有的存储库抽象,以保持简单。

Note: This is not tested. It's assuming that the child item collection is of type ICollection. (I usually have IList and then the code looks a bit other.) I've also stripped away all repository abstractions to keep it simple.

我不知道这是否是一个很好的解决方案,但我相信,必须做好这些工作,以便在导航集合中处理各种变化。我也很高兴看到一个更简单的方法。

I don't know if that is a good solution but I believe that some kind of hard work along these lines must be done to take care of all kinds of changes in the navigation collection. I would be happy as well to see an easier way.

这篇关于无法更改关系,因为一个或多个外键属性不可为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆