【问题标题】:LINQ to SQL: Composite FK only half nullableLINQ to SQL:复合 FK 只有一半可以为空
【发布时间】:2013-07-26 19:18:01
【问题描述】:

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

【问题讨论】:

  • 我无法直接回答这个问题,但我认为值得考虑为这一操作绕过 linq2sql 并使用 SqlCommand 之类的东西。
  • 您的所有者和事物表的主键是什么?
  • Owner上的PK是SiteId, OwnerId,Thing上的PK是SiteId, ThingId

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


【解决方案1】:

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


LINQ 正在积极阻止这变得更容易。在ChangeTracker.SynchDependentData() 中,检查每一列以查看它是否属于任何关联,如果该列属于则抛出异常

  1. 设置为空

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多