无法确定相关操作的有效排序

时间:2013-01-04 07:50:14

标签: entity-framework

这是我的模特

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

这是我的错误

  

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

10 个答案:

答案 0 :(得分:11)

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

例如,在以下情况中可能会发生这种情况:

  1. DepartmentId设置为零或任何其他不是有效外键的值。
  2. Department为null或者是一个Department对象,包含其自己的DepartmentId属性的空值。
  3. 此配置将导致Entity Framework失败,因为它尝试查找主键为零的部门,该部门可能不存在。
  4. 当我将一个对象映射到另一个对象并且错误地将外键设置为零而不是将其设置为null时,我遇到了这个异常。

    我不能说这个配置是导致你的异常而没有看到属性的实际值的原因,但它是一种可能性。

答案 1 :(得分:4)

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

答案 2 :(得分:4)

在我的情况下,它是由于在创建这样的东西时在另一个新对象中嵌套一个新的依赖对象引起的:

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

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

答案 3 :(得分:3)

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

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

答案 4 :(得分:2)

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

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

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

答案 5 :(得分:1)

我创建了一个sample project,可以在有两个关系时模拟错误。基本上这个想法是你有一个订单列表的客户。然后在客户上,您要存储其他属性以标记当前订单。这导致了两个&#34;实体框架在一次交易中存储和删除问题的关系。

最好创建一个布尔标志&#34; IsCurrent&#34;在订单和过滤器上。它还可以在客户上创建自动进行过滤的属性或扩展。这已经在this帖子中解释过了。

我认为除了使用两次调用SaveChanges之外别无他法,因为那时你会抛弃UnitOfWork的想法。

答案 6 :(得分: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;
            }

答案 7 :(得分:1)

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

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

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

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

答案 8 :(得分: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。

它有效并且还以视觉上吸引人的方式插入我的数据(至少对我而言)enter image description here

答案 9 :(得分:0)

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

IN:public ActionResult Create(OfficeRecordModel officeData)

我们有:

Region

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

办公室实体:

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

Office表格中包含我们未设置的身份ID。所以.. EF使用0.好吧,我们在Office表中有一个ID = 0的记录(在这个递归的自引用表中我们的root office)。

要解决此问题,我们将身份ID设置为-1。因此,现有密钥不再存在冲突。最终忽略-1并设置标识。

添加:newOffice.ID = -1;做了伎俩。