使用嵌套POCO进行LINQ To SQL操作(插入/更新)所需的帮助

mwj*_*son 7 .net orm poco linq-to-sql

好吧,我一直在尝试将我的模型转换为使用LINQ,但不想丢弃我当前的DTO和它们分散在域中的接口.

我设法找到这篇博文,其中很好地概述了这个过程:

在LINQ To SQL中实现POCO

我已经设法将记录检索到对象正常工作,但是,由于我的模型的嵌套特性,我似乎无法为子对象添加工作.也就是说,如果我创建一个子对象,并设置对所需父对象的引用,LINQ to SQL仍会抛出一个异常,说明子对父对象的引用为null.如果我尝试添加一个普通的旧父对象,它会成功,但直接添加子对象会失败

这是我的失败测试:

    [Test]
    public void AddSelectionShouldAddSelectionToMarket()
    {
        Market market = (Market) new Repository().GetMarket(1);

        Selection selection = new Selection();
        selection.Market = market;

        new Repository().AddSelection(selection);

        Assert.IsTrue(selection.SID > 0);
    }
Run Code Online (Sandbox Code Playgroud)

这是错误消息:

System.InvalidOperationException:尝试删除市场和选择之间的关系.但是,其中一个关系的外键(Selection.MID)不能设置为null.

2个对象的相关部分:

[DataContract]
public class Selection : ISelection
{
    private int mID;
    [DataMember]
    public int MID
    {
        get { return this.mID; }
        set { this.mID = value; }
    }

    private Market market;
    [DataMember]
    public Market Market
    {
        get { return this.market; }
        set
        {
            this.market = value;
            this.mID = value.MID;
        }
    }
}

[DataContract]
public class Market : IMarket
{
    private int mID;
    [DataMember]
    public int MID
    {
        get { return this.mID; }
        protected set { this.mID = value; }
    }

    private List<Selection> selections;
    [DataMember]
    public List<Selection> Selections
    {
        get { return this.selections; }
        set
        {
            this.selections = value;
            // For LINQ
            foreach (Selection selection in selections)
            {
                selection.MID = mID;
                selection.Market = this;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的DA代码:

        MarketsDataContext context = new MarketsDataContext();

        DataLoadOptions options = new DataLoadOptions();
        options.LoadWith<Selection>(s => s.Prices);
        options.LoadWith<Market>(m => m.Selections);

        context.LoadOptions = options;
        return context;
Run Code Online (Sandbox Code Playgroud)

和;

    public void AddSelection(ISelection selection)
    {
        using (MarketsDataContext context = MarketsDataContext.GetContext())
        {
            context.Selections.InsertOnSubmit((Selection) selection);
            context.SubmitChanges();
        }
    }
Run Code Online (Sandbox Code Playgroud)

最后我的XML映射:

  <Table Name="dbo.Markets" Member="Markets">
    <Type Name="Market">
      <Column Name="MID" Member="MID" Storage="mID" DbType="Int NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" />
      <Association Name="FK_Market-Selections" Member="Selections" Storage="selections" ThisKey="MID" OtherKey="MID" DeleteRule="NO ACTION"  />
    </Type>
  </Table>

  <Table Name="dbo.Selections" Member="Selections">
    <Type Name="Selection">
      <Column Name="SID" Member="SID" Storage="sID" DbType="Int NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" />
      <Column Name="MID" Member="MID" Storage="mID" DbType="Int NOT NULL" />
      <Association Name="FK_Market-Selections" Member="Market" Storage="market" ThisKey="MID" OtherKey="MID" IsForeignKey="true" />
    </Type>
  </Table>
Run Code Online (Sandbox Code Playgroud)

那么,有人能指出我正确的方向吗?我一直在寻找......

编辑:

这是我的测试失败的堆栈跟踪:

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 BetMax.DataModel.Repository.AddSelection(ISelection selection) in Repository.cs: line 68
at BetMax.DataModel.Test.ModelTest.AddSelectionShouldAddSelectionToMarket() in ModelTest.cs: line 65 
Run Code Online (Sandbox Code Playgroud)

而我的GetMarket方法:

    public IMarket GetMarket(int MID)
    {
        Market market;
        using (MarketsDataContext context = MarketsDataContext.GetContext())
        {
            market = context.Markets.Single(m => m.MID == MID);
        }
        return market;
    }
Run Code Online (Sandbox Code Playgroud)

编辑2:

好吧,补充一下

DeleteOnNull="true"
Run Code Online (Sandbox Code Playgroud)

选择XML映射中的外键已删除了外键错误,但现在我在其中一个Selections的子对象上得到一个空引用,说它对Selection的引用为null,即使在初始化Selection时没有设置其变量(在外键之外).我甚至尝试创建一个子对象,并正确设置其引用但仍然收到此错误:

System.NullReferenceException: Object reference not set to an instance of an object.
at BetMax.DTO.Price.set_Selection(Selection value) in Price.cs: line 25
at System.Data.Linq.Mapping.PropertyAccessor.Accessor`3.SetValue(ref T instance, V value)
at System.Data.Linq.Mapping.MetaAccessor`2.SetBoxedValue(ref Object instance, Object value)
at System.Data.Linq.ChangeProcessor.ClearForeignKeysHelper(MetaAssociation assoc, Object trackedInstance)
at System.Data.Linq.ChangeProcessor.ClearForeignKeyReferences(TrackedObject to)
at System.Data.Linq.ChangeProcessor.PostProcessUpdates(List`1 insertedItems, List`1 deletedItems)
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
at BetMax.DataModel.Repository.AddSelection(ISelection selection) in Repository.cs: line 68
at BetMax.DataModel.Test.ModelTest.AddSelectionShouldAddSelectionToMarket() in ModelTest.cs: line 69 
Run Code Online (Sandbox Code Playgroud)

价格是另一个对象,构造与选择与市场相关(1选择有很多价格,1市场有很多选择)等.

Gee*_*key 0

我建议将您的代码发送给 Sidar Ok。他是一个好人,会给你指明正确的方向。或者至少在他的博客上发表评论,指出你的问题。