在实体框架中设置外键值为空
本文关键字:键值 设置 实体 框架 | 更新日期: 2023-09-27 18:16:52
当从记录中删除外键值时,我无法将记录保存到SQL Server数据库。
作为一个例子,我有一个现有的BatchDetail记录,其主键BatchDetailID = 10。并且它与现有的RunDetail记录相关联,该记录具有主键RunDetailID = 20和外键BatchDetailID = 10。我想通过设置RunDetails来解除RunDetail与BatchDetail的关联。BatchDetailID为空
错误信息如下:
发生了一个引用完整性约束冲突:"BatchDetail"的属性值。关系一端的BatchDetailID与RunDetail的属性值不匹配。"BatchDetailID"
下面是我的类定义:
public class RunDetail
{
public int RunDetailID { get; set; }
public Nullable<int> BatchDetailID { get; set; }
public virtual BatchDetail BatchDetail { get; set; }
}
public class BatchDetail
{
public int BatchDetailID { get; set; }
public virtual ICollection<RunDetail> RunDetails { get; set; }
}
当RunDetail
对象具有BatchDetailID
值时发生错误,并且我试图将其设置回null:
public class MyController : Controller
{
private ISvr _myService;
public ISvr MyService
{
get { return _myService ?? (_myService = new MyHandler().GetMyService()); }
set
{
_myService = value;
}
}
public void UpdateBatch(int id)
{
foreach (var batchDetail in MyService.ReadBatchDetails(id))
{
var runDetail = MyService.ReadRunDetail(batchDetail.RunDetailID);
runDetail.BatchDetailID = null;
runDetail.BatchDetail = null; // I have tried with, and without, this line
MyService.UpdateRun(runDetail );
}
}
}
public class MyHandler
{
public ISvr GetMyService()
{
return new MySvr();
}
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
public class MySvr : IMySvr
{
public void UpdateRun(RunDetail runDetail)
{
using (var myEntities = new MyEntities())
{
myEntities.RunDetails.Attach(runDetail); // This is where the exception hits
myEntities.Entry(runDetail).State = EntityState.Modified;
myEntities.SaveChanges();
}
}
}
所有其他记录更新,包括将外键值更改为另一个值,都可以正常工作。
有人能看出我的缺点是什么吗?
问题的根源在于我的问题中没有包括的一个方法。当我检索父BatchDetail
记录时,我包含了"RunDetails"记录:
public List<BatchDetail> ReadBatchDetails(int id)
{
using (var myEntities = new MyEntities())
{
return myEntities.BatchDetails
.Include("RunDetails") // This is the problem
.AsNoTracking().ToList();
}
}
通过创建一个不包含Include("RunDetails")
的新方法,解决了这个问题:
public List<BatchDetail> ReadBatchDetailsWithoutRunDetails(int id)
{
using (var myEntities = new MyEntities())
{
return myEntities.BatchDetails.AsNoTracking().ToList();
}
}
我按如下方式插入1个BatchDetail和1个RunDetail
using (var db = new AppContext())
{
db.BatchDetails.Add(new BatchDetail { Id = 1 });
db.RunDetails.Add(new RunDetail { Id = 1, BatchDetailId = 1 });
db.SaveChanges();
}
下面是抛出相同错误的结果:
using (var db = new AppContext())
{
// This is okay.
var x = new RunDetail { Id = 1, BatchDetailId = 1, BatchDetail = new BatchDetail { Id = 1 } };
db.RunDetails.Attach(x);
}
using (var db = new AppContext())
{
// This is okay.
var x = new RunDetail { Id = 1, BatchDetailId = null, BatchDetail = null };
db.RunDetails.Attach(x);
}
using (var db = new AppContext())
{
// This is okay.
var x = new RunDetail { Id = 1, BatchDetailId = 1, BatchDetail = null };
db.RunDetails.Attach(x);
}
using (var db = new AppContext())
{
// A referential integrity constraint violation occurred: The property
// value(s) of 'BatchDetail.Id' on one end of a relationship do not match the property
// value(s) of 'RunDetail.BatchDetailId' on the other end.
var x = new RunDetail { Id = 1, BatchDetailId = null, BatchDetail = new BatchDetail { Id = 1 } };
db.RunDetails.Attach(x);
}