7

さて、モデルを 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);
    }

エラーメッセージは次のとおりです。

System.InvalidOperationException: Market と Selection の間の関係を削除しようとしました。ただし、リレーションシップの外部キー (Selection.MID) の 1 つを 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;
            }
        }
    }
}

私の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;

と;

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

そして最後に私の 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>

それで、誰かが私を正しい方向に向けることができますか?私は何時間も探していました...

編集:

テスト失敗のスタックトレースは次のとおりです。

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 

そして私の GetMarket メソッド:

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

編集2:

さて、追加

DeleteOnNull="true"

XML マッピングの外部キーを選択すると、外部キー エラーが削除されましたが、現在、選択の子オブジェクトの 1 つで null 参照を取得しています。選択が変数セットなしで初期化されているにもかかわらず、選択への参照が null であると言っています。 (外部キーの外)。私は子オブジェクトを作成しようとしましたが、その参照を正しく設定しましたが、まだこのエラーが発生しています:

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 

価格は別のオブジェクトであり、その選択が市場に関連するのと同じように構築されます (1 つの選択には多くの価格があり、1 つの市場には多くの選択があります) など。

4

5 に答える 5

4

問題はテスト方法にあると思います。DataContext を使用してリポジトリを作成しましたが、別のリポジトリを使用して送信を行いました。

[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);
}

リポジトリを作成し、テスト メソッドで使用します。

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

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

    repository.AddSelection(selection);

    Assert.IsTrue(selection.SID > 0);
}
于 2008-11-18T09:30:39.157 に答える
2

しばらく経ち、おそらくすでに問題は解決されていると思いますが、そうではないかもしれません...

あなたのデータ構造はこれに似ていると思います:

Market
======
Market_ID      int not null identity (1, 1)


Selection
=========
Selection_ID   int not null identity (1, 1)
Market_ID      int (FK to Market)
Selection_Name varchar(50)

新しいマーケットと新しいセレクションを同時に追加するには:

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

market.Selections.Add(selection);
DataContext.Markets.InsertOnSubmit(market);
DataContext.SubmitChanges();

新しいセレクションを既存のマーケットに追加するには:

Selection selection = new Selection();
Market market = DataContext.Markets.Where(a => a.Market_ID == 7).Single();

market.Selections.Add(selection);
DataContext.SubmitChanges();

マーケットの最初のセレクションを更新するには:

Selection selection = DataContext.Markets.Where(a => a.Market_ID == 7).Selections.First();

selection.Selection_Name = "New Name";
DataContext.SubmitChanges();
于 2010-02-04T23:39:48.647 に答える
2

推測だけどここにあるかもしれない

public Market Market
{
    get { return this.market; }
    set
    {
        this.market = value;
        this.mID = value.MID;
    }
}

Market に設定した値が null の場合はどうなりますか? null.MID を解決できないため、最後の行は無効になります。セッターにこれが必要かもしれません:

    set
    {
        this.market = value;
        this.mID = (value == null) ? null : value.MID;
    }

また、MIDはnull可能でなければなりません

int? MID
于 2008-11-18T09:32:26.640 に答える
2

あなたの新しい問題のために; この問題は、Price の選択プロパティへの null 割り当てで発生します。あなたのコードでそれをしましたか?例外が発生したコード部分をもう一度教えてください。Price エンティティへの割り当てを意味します...

コメントに従って編集: 前に GeekyMonkeys の投稿で述べたように、null コントロールの例外が原因だと思います。Selection クラスの初期化では、Price プロパティを null に設定する必要がありますが、null が割り当てられると null 参照がスローされます。したがって、価格プロパティのセットで null コントロールを実行する必要があります。

private List<Price> prices
[DataMember]
public List<Price> Prices
{
    get { return this.prices; }
    set
    {
        if(value != null)
        {
          this.pricess = value;
          // For LINQ             
          foreach (Price price in prices)
          {
            price.MID = mID;
            price.Selection = this;
          }
       }
    }
}
于 2008-11-18T12:57:43.090 に答える
0

コードを Sidar Ok に送信することをお勧めします。彼はいい人で、あなたを正しい方向へと導いてくれるでしょう。または、少なくとも彼のブログにコメントを投稿して、ここであなたの質問を指摘してください.

于 2008-11-18T09:29:51.170 に答える