Entity framework 无法确定从属操作的有效顺序
这是我的模型Entity framework 无法确定从属操作的有效顺序,entity-framework,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 virt
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; }
公共字符串内容{get;set;}
公共常见问题解答回复{set;get;}
公共整数?ReplyId{get;set;}
公共ICollection子项{get;set;}
[ForeignKey(“WriterId”)]
公共虚拟用户配置文件编写器{get;set;}
公共虚拟整数?WriterId{get;set;}
公共状态状态{get;set;}
[外键(“部门ID”)]
公共虚拟部门部门{get;set;}
公共虚拟整数?部门ID{get;set;}
这是我的错误
无法确定从属操作的有效顺序。依赖关系可能由于外键约束、模型要求或存储生成的值而存在
避免此错误的简单方法是先创建主对象,然后保存更改,然后在再次调用SaveChanges之前创建从属对象
在这种情况下,首先创建上面显示的对象,保存更改,然后创建Faq子对象,将其添加到集合中并将其设置为回复,然后再次保存更改。另一个可能的原因是外键属性设置不正确 例如,这可能发生在以下场景中:
在没有看到属性的实际值的情况下,我不能说此配置是导致异常的原因,但这是一种可能性。FWIW,我刚刚花了一个上午调试了EF 6.1中的一个类似问题。在我的例子中,这是由于意外地混合了不同上下文所拥有的对象:在一个上下文所拥有的对象中设置导航属性的值,而另一个上下文所拥有的对象。因此我遇到了这个问题,我想分享我解决这个问题的方法,它不像调用保存更改两次那么简单,但它比那种方法有一些优点 我有一种情况,我希望所有的记录要么成功要么失败,部分插入的孩子是不可接受的。我也不想编写代码来删除父级,如果子级失败了(如果代码中有bug,如果代码失败了,等等) 第二,可以有一组记录,我希望所有这些记录在一次交易中成功或失败。从本质上讲,我对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手动将孩子连接到家长
它起作用了,还以一种视觉上吸引人的方式插入了我的数据(至少对我来说)这发生在我身上。EF 6.1/MVC 中:公共操作结果创建(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; }
public int ID{get;set;}
公共可为空的父项{get;set;}
公共整数级别{get;set;}
公共字符串短名称{get;set;}
公共字符串LongName{get;set;}
公共bool IsActive{get;set;}
Office表有一个我们没有设置的标识ID。所以EF使用0。我们在Office表中有一条ID=0的记录(在这个递归自引用表中,我们的根Office)
为了解决这个问题,我们将标识ID设置为-1。因此,现有密钥中不再存在冲突。最终会忽略-1,并设置标识
添加:newOffice.ID=-1;做了这个把戏。我创建了一个模拟两个关系时的错误的。基本上,你的想法是,你有一个客户的订单清单。然后,您要在客户上存储一个附加属性来标记当前订单。这导致实体框架在一个事务中存储和删除“两个”关系时出现问题
最好在订单上创建一个bool标志“IsCurrent”,并对其进行筛选。也可以在客户上创建一个属性或扩展来自动进行过滤。这已经在帖子中解释过了
我认为除了使用两个调用来保存更改之外没有其他方法,这很糟糕,因为这样你就放弃了UnitOfWork的想法。在我的例子中,这是由于在创建过程中将一个新的依赖对象嵌套在另一个新对象中造成的,如下所示:
var mySecondaryObject = new MyClass1 { ... };
var myPrimaryObject = new MyClass2 { Child = mySecondaryObject, ... };
dbContext.MyClass2Collection.Add(mySecondNewOject);
dbContext.SaveChanges();
删除嵌套引用并在创建主对象后分配子对象解决了此问题。可能很晚,但我遇到了相同的问题,并解决了此问题。如果存在父对象,则将子对象添加到父对象的子对象属性(如果不只是保存对象)
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;
}
下面是我们如何解决这个问题的。我们有一个实体,它定义了sql查询来填充实体。该实体有一列标记为键,并具有insert、update和delete CRUD方法。键列由Oracle存储过程自动填充,并在游标中返回。插入新行时出现此错误 经过研究和调查,我们发现问题是由于insert存储过程被作为参数值传递给key column,并且在存储过程返回bac时被填充