如何在 C# 中插入依赖于 LINQ to SQL 实体而无需手动更新 ID?

How to insert depending LINQ to SQL entities without manual ID update in C#?

我有2个模型。

型号Foo

[System.Data.Linq.Mapping.Table(Name = ...)]
public class Foo
{
  [System.Data.Linq.Mapping.Column(IsPrimaryKey = true, IsDbGenerated = true)]
  public int ID { get; set; }

  [System.Data.Linq.Mapping.Column(IsPrimaryKey = true)]
  public int BarID { get; set; }
  
  // 1:1 association - foo <> bar
  [System.Data.Linq.Mapping.Association(Name = "FK_Foo_Bar", Storage = "mBar", OtherKey = "ID", ThisKey = "BarID")]
  public Bar CurrentRevision
  {
    get { return mBar.Entity; }
    set { mBar.Entity = value; }
  }
  
  private System.Data.Linq.EntityRef<Bar> mBar = new System.Data.Linq.EntityRef<Bar>();
}

型号酒吧

[System.Data.Linq.Mapping.Table(Name = ...)]
public class Bar
{
  [System.Data.Linq.Mapping.Column(IsPrimaryKey = true, IsDbGenerated = true)]
  public int ID { get; set; }

  [System.Data.Linq.Mapping.Column(IsPrimaryKey = true)]
  public int FooID { get; set; }
  
  // 1:1 association - bar <> foo
  [System.Data.Linq.Mapping.Association(Name = "FK_Bar_Foo", Storage = "mFoo", OtherKey = "ID", ThisKey = "FooID")]
  public Foo Folder
  {
    get { return mFoo.Entity; }
    set { mFoo.Entity = value; }
  }
  
  private System.Data.Linq.EntityRef<Foo> mFoo = new System.Data.Linq.EntityRef<Foo>();
}

我想像这样插入一个 Foo 和一个 Bar

lFoo = new Foo();
DataContext.Foos.InsertOnSubmit(lFoo);    

lBar = new Bar();
DataContext.Bars.InsertOnSubmit(lBar);    

lBar.Foo = lFoo; // link foo to bar
lFoo.Bar = lBar; // link bar to foo

DataContext.SubmitChanges();

lFoo 的一行和 lBar 的一行已添加到数据库中,但 FooIDBarID 字段仍为零。

有没有办法让框架使用正确的 ID 自动更新列 FooIDBarID,而不是手动执行此操作?

我通过阅读 MSDN 上的 LINQ to SQL documentation 发现以下问题导致了此问题:

  1. multiple IsPrimaryKey in one class表示复合键,DB没有
  2. 缺少 IsForeignKey 属性
  3. InsertOnSubmits() 调用之后直接双向链接对象将不起作用,因为它会引发 A cycle was detected in the set of changes 异常。

所以正确的方法是

型号Foo

[System.Data.Linq.Mapping.Table(Name = ...)]
public class Foo
{
  [System.Data.Linq.Mapping.Column(IsPrimaryKey = true, IsDbGenerated = true)]
  public int ID { get; set; }

  [System.Data.Linq.Mapping.Column]
  public int BarID { get; set; }

  // 1:1 association - foo <> bar
  [System.Data.Linq.Mapping.Association(Name = "FK_Foo_Bar", Storage = "mBar", OtherKey = "ID",
    ThisKey = "BarID", IsForeignKey=true)]
  public Bar CurrentRevision
  {
    get { return mBar.Entity; }
    set { mBar.Entity = value; }
  }

  private System.Data.Linq.EntityRef<Bar> mBar = new System.Data.Linq.EntityRef<Bar>();
}

型号酒吧

[System.Data.Linq.Mapping.Table(Name = ...)]
public class Bar
{
  [System.Data.Linq.Mapping.Column(IsPrimaryKey = true, IsDbGenerated = true)]
  public int ID { get; set; }

  [System.Data.Linq.Mapping.Column]
  public int FooID { get; set; }

  // 1:1 association - bar <> foo
  [System.Data.Linq.Mapping.Association(Name = "FK_Bar_Foo", Storage = "mFoo", OtherKey = "ID",
    ThisKey = "FooID", IsForeignKey=true)]
  public Foo Folder
  {
    get { return mFoo.Entity; }
    set { mFoo.Entity = value; }
  }

  private System.Data.Linq.EntityRef<Foo> mFoo = new System.Data.Linq.EntityRef<Foo>();
}

插入

lFoo = new Foo();
DataContext.Foos.InsertOnSubmit(lFoo);    

lBar = new Bar();
DataContext.Bars.InsertOnSubmit(lBar);    

DataContext.SubmitChanges();    

lBar = lFoo; // link foo to bar
lFoo = lBar; // link bar to foo

DataContext.SubmitChanges();

作为侧节点,遗憾的是,使用 IsForeignKey 属性值会改变查询行为(例如,LINQ to SQL 生成 CROSS JOINS 而不是 INNER JOINS)和我的整体程序逻辑。