25

这是我的模型

public string Content { get; set; }

public Faq Reply { set; get; }

public int? ReplyId { get; set; }

public ICollection<Faq> Children { get; set; }

[ForeignKey("WriterId")]
public virtual UserProfile Writer { get; set; }

public virtual int? WriterId { get; set; }

public Status Status { get; set; }

[ForeignKey("DepartmentId")]
public virtual Department Department { get; set; }

public virtual int? DepartmentId { get; set; }

这是我的错误

无法确定相关操作的有效排序。由于外键约束、模型要求或存储生成的值,可能存在依赖关系。

4

11 回答 11

10

另一个可能的原因是外键属性设置不正确。

例如,这可能发生在以下场景中:

  1. DepartmentId 设置为零或任何其他不是有效外键的值。
  2. Department 或者为 null,或者它是一个 Department 对象,该对象包含其自己的 DepartmentId 属性的 null 值。
  3. 此配置将导致 Entity Framework 失败,因为它尝试查找主键为零的部门,而该部门可能不存在。

当我将一个对象映射到另一个对象并且我错误地将外键设置为零而不是将其设置为空时,我遇到了这个异常。

在没有看到属性的实际值的情况下,我不能说这种配置是导致您的异常的原因,但这是一种可能性。

于 2014-12-10T16:29:31.673 回答
4

避免此错误的简单方法是首先创建主对象 SaveChanges,然后在再次调用 SaveChanges 之前创建依赖对象。

在这种情况下,首先创建上面显示的对象 SaveChanges,然后创建 Faq 子对象,将其添加到集合中并将其设置为回复,然后再次设置 SaveChanges。

于 2014-01-04T16:52:16.097 回答
4

FWIW,我刚刚花了一个上午在 EF 6.1 中调试了一个类似的问题。在我的情况下,这是由于意外混合了不同上下文拥有的对象:在一个上下文拥有的对象中设置导航属性的值,以及不同上下文拥有的对象。

于 2015-05-06T19:16:07.647 回答
4

我有一个具有自引用导航属性的实体类。如果与该导航属性关联的外键属性设置为零,则会失败并出现此错误。

如果我将它设置为另一个无效值,例如 -1 或数据库中不存在的另一个值,它不会收到此错误。如果我更改导航属性以引用错误的实体(因此它不是自引用的),即使使用零也不会出现此错误。

所以显然 EF 为自引用导航属性做了一些特殊的零。我知道该关系定义正确,因为我使用它的查询提取了正确的数据。

我能够通过使用 null 而不是零来解决我的问题。无论如何,这对我来说确实是合适的价值。

于 2019-06-18T15:15:02.980 回答
4

在我的情况下,这是由于在创建过程中将新的依赖对象嵌套在另一个新对象中引起的,如下所示:

var mySecondaryObject = new MyClass1 { ... };
var myPrimaryObject = new MyClass2 { Child = mySecondaryObject, ... };
dbContext.MyClass2Collection.Add(mySecondNewOject);
dbContext.SaveChanges();

在创建主对象后删除嵌套引用并分配子对象解决了这个问题。

于 2017-06-11T17:53:56.673 回答
3

以下是我们解决此问题的方法。我们有定义了 sql 查询来填充实体的实体。该实体有一列标记为键,并具有插入、更新和删除 CRUD 方法。使用 Oracle 存储过程自动填充键列并在游标中返回。插入新行时出现此错误。

经过研究和调查,我们发现问题是由于插入存储过程作为参数值传递键列,并且在存储过程返回键列自动生成的值时也被填充。

我们从插入 SP 中删除了键列参数,问题得到解决。

于 2017-11-21T15:58:10.890 回答
1

这发生在我身上。EF 6.1/MVC

IN:公共 ActionResult 创建(OfficeRecordModel officeData)

我们有:

Office newOffice = new Office();
newOffice.Parent = officeData.Parent;
newOffice.Level = officeData.Level != null ? officeData.Level.Value : -1;
newOffice.ShortName = officeData.ShortName.Trim();
newOffice.LongName = officeData.LongName.Trim();
newOffice.IsActive = officeData.IsActive;                        
dbCtxt.Office.Add(newOffice);
dbCtxt.SaveChanges();

我得到:{“无法确定依赖操作的有效排序。由于外键约束、模型要求或存储生成的值,可能存在依赖关系。”}

办公实体:

public int ID { get; set; }
public Nullable<int> Parent { get; set; }
public int Level { get; set; }
public string ShortName { get; set; }
public string LongName { get; set; }
public bool IsActive { get; set; }

Office 表有一个我们没有设置的身份 ID。所以.. EF 使用 0。好吧,我们在 Office 表中有一条 ID=0 记录(此递归自引用表中的根办公室)。

为了解决这个问题,我们将身份 ID 设置为 -1。因此,现有密钥中不再有冲突。-1 最终被忽略并设置身份。

添加:newOffice.ID = -1;成功了。

于 2016-03-03T18:11:03.550 回答
1

可能晚了,但我遇到了同样的问题并解决了这个问题。如果有父级,则将子级添加到父子级属性,如果不只是保存对象。

            using (var context = new MyEntities())
            {
                child.CreatedOn = DateTime.Now;

                if (child.ParentId == null)
                {
                    context.Things.Add(child);
                }
                else
                {
                    var parent = context.Things.Where(x => x.Id == child.ParentId).SingleOrDefault();

                    if(parent == null)
                    {
                        return false;
                    }

                    parent.Things.Add(child);
                }

                context.SaveChanges();

                return true;
            }
于 2017-10-24T11:25:59.040 回答
1

当您有两个关系时,我创建了一个示例项目来模拟错误。基本上,这个想法是您有一个带有订单列表的客户。然后在您要存储的客户上附加一个属性来标记当前订单。这导致实体框架在一个事务中存储和删除问题的“两个”关系。

最好在订单上创建一个布尔标志“IsCurrent”并对其进行过滤。也可以在客户上创建一个自动进行过滤的属性或扩展。这已经在这篇文章中解释过了。

我认为除了使用两次对 SaveChanges 的调用之外别无他法,这很糟糕,因为你会抛弃 UnitOfWork 的想法。

于 2016-09-17T10:39:08.693 回答
0

所以遇到了这个问题,想分享一下我解决它的方法,不是调用两次保存更改那么简单,但是比那个方法有一些优势。

我有一种情况,我希望所有记录都成功或失败,部分插入子项是不可接受的。我也不想编写代码来删除父级,如果子级失败(如果该代码中有错误,如果该代码失败怎么办等)。

其次,可能有一组记录,我希望所有这些记录在一个事务中成功或失败。本质上,我对 EF 非常具体(我的 EF 版本是 6.1.3)。此外,我只在父子关系中深入了一层,而不是任意数量的深度。

int tempId = -1;
int parentTempId = -1;
foreach(var record in recordsToSave)
{
    var childRecords = record.ChildRecords.ToList();

    record.ChildRecords.Clear();

    record.RecId = tempId;
    parentTempId = tempId;
    tempId--;

    _db.Records.Add(record);

    foreach(var childRecord in childRecords)
    {
        childRecord.RecId = tempId;
        childRecord.ParentRecId = parentTempId;
        tempId--;
        _db.Records.Add(childRecord);
    }
}

using (TransactionScope tran = new TransactionScope())
{
    _db.SaveChanges();
    tran.Complete();
}
  • 首先,我清除了子集合并将其复制到临时列表中。EF 与我的关系有问题。
  • 我创建了一个临时 id 并将其分配给父记录,并将其存储起来供孩子以后使用。
  • 我通过我的临时 ID 手动将孩子连接到父母。

它起作用了,它还以一种视觉上吸引人的方式插入了我的数据(至少对我来说)在此处输入图像描述

于 2016-02-18T16:19:33.170 回答
0

在我的情况下,由于删除了它们之间具有循环引用的表而产生了此错误。like 数据库不允许我删除页面行,因为它在书表中有针对书签页面的引用。也在这里重现了这种情况。


public class Book
{
   public int Id { get; set; }
   public int Name { get; set; }

   [ForeignKey("BookMarkedPage")]
   public int BookMarkedPageId { get; set; }
   public Page BookMarkedPage { get; set; }
}

public class Page
{
        public int Id { get; set; }

        [ForeignKey("Book")]
        public int BookId { get; set; }
        public Book Book { get; set; }
}

解析度

有两种可能的替代方法来解决此错误

  1. 在从页表中删除页记录之前,首先从书表中删除书签页引用,然后尝试删除页行

  2. 或者不是创建一个循环引用,而是在页表中创建一个位isbookMarkedPage来标识一本书的书标记页


public class Book
{
   public int Id { get; set; }
   public int Name { get; set; }
}

public class Page
{
        public int Id { get; set; }

        [ForeignKey("Book")]
        public int BookId { get; set; }
        public Book Book { get; set; }

        public bool IsBookMarkedPage
}


于 2021-01-14T21:47:50.630 回答