LINQ to SQL:复合FK只有一半可以为空

时间:2013-07-26 19:18:02

标签: linq-to-sql composite-key sqlmetal

在使用复合键的多租户应用程序中 (例如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

1 个答案:

答案 0 :(得分:3)

设置ThingId = null而不是Thing = null。不要重复使用DataContext,否则可能会出现“外键已设置”异常。


LINQ正在积极地防止这种情况变得更容易。在ChangeTracker.SynchDependentData()中,检查每一列是否属于任何关联,如果列

则抛出异常
  1. 设为null

  2. 该关联有任何不可为空的列(!)

  3. 在我看来,这是LINQ-to-SQL中的一个错误。