在使用复合键的多租户应用程序中
(例如SiteId, $(Table)Id
)
对于一切,我有以下两个表:
Owner (
SiteId bigint NOT NULL,
OwnerId bigint NOT NULL,
ThingId bigint NULL
)
Thing (
SiteId bigint NOT NULL,
ThingId bigint NOT NULL
)
以及从Owner (SiteId, ThingId)
到Thing (SiteId, ThingId)
的外键。
如果我写这样的方法:
void RemoveThing(Owner owner)
{
owner.Thing = null;
db.SubmitChanges();
}
我得到了例外
System.InvalidOperationException: An attempt was made to remove a relationship between a
Thing and a Owner. However, one of the relationship's foreign keys (Owner.MultiId,
Owner.ThingId) cannot be set to null.
at System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData()
at System.Data.Linq.ChangeProcessor.ValidateAll(IEnumerable`1 list)
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
at proj.Program.RemoveThing() in C:\proj\Program.cs:line 115
要解决此问题,我可以将SiteId
的第二个副本(可能是ThingSiteId
)添加到Owner
表中。但它只会与SiteId相同,所以我会花费数据库大小和模式复杂性来解决我的ORM问题。
如何告诉LINQ to SQL它不需要担心外键关系的一半,只设置Owner.ThingId=NULL
?
答案 0 :(得分:3)
设置ThingId = null
而不是Thing = null
。不要重复使用DataContext
,否则可能会出现“外键已设置”异常。
LINQ正在积极地防止这种情况变得更容易。在ChangeTracker.SynchDependentData()
中,检查每一列是否属于任何关联,如果列
设为null
该关联有任何不可为空的列(!)
在我看来,这是LINQ-to-SQL中的一个错误。