10

LINQ-to-SQLを使用して、1対多の関係にある2つのテーブルを持つデータベースからデータをロードします(1つのレシピには多くの材料が含まれています)。

レシピをロードすると、LINQはIngredientオブジェクトをListBoxにバインドされているEntitySetに取得します。

レシピからいくつかの材料を削除したい場合、「レシピと材料の間の関係を削除しようとしました。しかし、関係の外部キーの1つ(Ingredient.RecipeID)をnullに設定できません。

DBMLファイルに「DeleteOnNull="true"」を追加することで、よく知られた解決策を使用してこの問題を解決しました。ただし、この設定を追加すると、DBから取得した成分オブジェクトを削除する場合にのみ問題が削除されます。

問題は、コードで作成され(レシピに追加され)、IngredientsのEntitySetコレクションに追加され、SubmitUpdatesが呼び出される前に削除されたIngredientオブジェクトにあります。その後、同じ例外が再び発生します。これは通常、ユーザーが材料を追加し、間違いを犯し、レシピから材料を消去するときに、新しい未保存のレシピで発生します。DBMLの両方の'AssociationName="Recipe_Ingredient"'行にDeleteOnNullを追加しました。

そのようなオブジェクトをどのように削除する必要がありますか?現時点で私が目にしている唯一の解決策は、DataContextの下にないコレクションに材料をロードし、保存するときにレシピからすべての材料を削除して、そのキャッシュから再度追加することです。

4

7 に答える 7

8
        try
        {
            // Needed for existing records, but will fail for new records
            yourLINQDataContext.Ingredients.DeleteOnSubmit(ingredient);
        }
        catch (Exception)
        {
            // Swallow
        }

        yourRecipeObject.Ingredients.Remove(ingredient);
于 2008-12-23T05:21:23.197 に答える
3

数日前に「データバインドされた WPF ダイアログのバッキング データ型を Ok/Cancel ボタンで設計するにはどうすればよいですか? 」と尋ねたときに、私が探していたものを探しているようです。

その答えは、 Linq からSql へのサンプル IEditable アダプターについて説明している Paul Stovell の興味深い投稿です。これにより、完全なカスタム作成レイヤーを通じて、基礎となる ORm 生成クラスから完全に分離することなく、一般化された方法で目的の「適用/キャンセル」セマンティクスを作成できます。

全体として、これは非常に巧妙なトリックであり、現在戦っている問題を本質的に回避することができます。:)

別の言い方をすれば、レシピと材料の関係が m:n ではなく 1:n である理由が気になります。シンプルにするためですか?多くのレシピでにんにくを使っています。:)

于 2008-12-23T05:51:50.297 に答える
2
// Create new entities
Cart c = new Cart();
CartEntry ce = new CartEntry();
ce.Cart = c;

// Delete the entry
c.CartEntries.Remove(ce);
dc.Cartentries.Attach(ce);
dc.CartEntries.DeleteOnSubmit(ce);

// Insert the cart into database
dc.Carts.InsertOnSubmit(c);
dc.SubmitChanges();

問題の説明: c と ce の両方のエンティティは、データ コンテキストに関連付けられていません。追跡されていません。EntitySet.Remove() (最初の削除行) は、c と ce の間の関係のみを削除します。c は関連付けられたカート エントリなしで存在できますが、ce は関連付けられたカートなしでは存在できません。これは、外部キー制約のためです。データベースに変更を送信すると、切断された ce も処理され、制約違反と例外が発生します。

追跡されていない切断されたカート エントリを取り除くには、それをデータ コンテキストにアタッチして (追跡されるようにする)、送信時に削除するようにマークする必要があります。変更を送信すると、カートのエントリは適切に削除され、例外は発生しません。

この問題の詳細については、http: //msdn.microsoft.com/en-us/library/bb546187%28v=VS.100%29.aspxを確認してください。

于 2010-05-31T10:34:05.570 に答える
0

GUIのイベントから保存コードを切り離す必要があります。ほこりが落ち着く前に、データベースに保存することに少し熱心で、そこに到達しなかったものをキューに入れてデータベースから削除しているようです。そもそも、ユーザーが変更を「コミット」するポイントを特定し、その時点でGUIの完全な状態を処理できれば、それが最善です。これにより、大量のスパゲッティコードを節約できます。

また、エンティティに自動番号IDがあるかどうか、または他のIDメカニズムを使用しているかどうかも知りたいと思います。おそらく、まだコミットされていないIngredientレコードのデータベースにDELETEを送信している可能性があります。それらに、NULL IDが含まれている場合、linqは厄介になる可能性があると思います。

テキストライターをDataContext.Logに接続して、実行を開始する直前にどのような種類のSQLが生成されるかを確認しましたか?

于 2008-12-23T02:44:47.990 に答える
0

同様の問題が発生しています。回避策として、DataContext.GetChanges() を呼び出す必要があります。その後、すべてが再びうまくいったようです:)

エンティティのプロパティではなく列にバインドしているため、参照コレクションが更新されないという別の問題が発生する可能性があります (他の誰かによって既に述べられていますが、事実を強制しています)。

于 2009-03-09T11:29:14.500 に答える
0

回答ありがとうございます。投稿を調べて、できることを確認します。この問題が発生していることにさえ驚いていると言わざるを得ません。LINQ が提供するデータの「キャッシュ」にレコードを追加し、それらの一部を消去してからコミットすることを決定できるのは、私には非常に自然なことのように思えます。変更追跡はそれを処理できるはずです。私はLINQを始めたばかりなので、コードのどこかで愚かな間違いをしている可能性があります(最初ではないでしょう)。

他のメモ: ニンニクが多くのレシピに属している可能性があることは非常に正しいです (私のカクテルレシピは考えていません!)。私は実際にそれを Article オブジェクト/テーブルでモデル化しています。しかし、レシピの場合、量が必要です。したがって、私のモデルでは、1:n の材料を持つレシピがあり、それぞれに数量、記事への 1:1 リンク (名前、AlcoholContent、および交換可能な階層を確立するためのデータがあります) と、ユニットへの 1:1 リンク (数量を意味のあるものにするため)。したがって、ある意味では、Ingredient テーブルは Recipe と Article の間に M:N の関係を作成し、同時にリンクされた個々のペアにいくつかの追加情報を追加します。

于 2008-12-23T07:04:40.150 に答える
0

私はまったく同じ問題を抱えていました。親/子階層があり、データベースに保存せずに子エンティティを追加および削除すると、「リレーションシップを削除しようとしました」という例外が発生しました。

この問題は、保存する前に、子のオブジェクト スタイル プロパティを別の linq-sql エンティティに設定した場合にのみ発生することがわかりました。例えば

1.これによりエラーが発生します

 RetailAccountCustomerCard racc = new RetailAccountCustomerCard();

 Card addedCard = _idc.Cards.Where(c => c.CardId == card.CardId).ToList().First();

 racc.Card = addedCard;

 this.CurrentCustomer.RetailAccountCardsBindingList.Add(racc); 

 // Some code triggered by the user before saving to the db

 CurrentCustomer.RetailAccountCardsBindingList.Remove(racc);

2.これはエラーを作成しません

 RetailAccountCustomerCard racc = new RetailAccountCustomerCard();

 racc.CardId = card.CardId;  // note that I have set the Id property not the object

 this.CurrentCustomer.RetailAccountCardsBindingList.Add(racc); 


 // Some code triggered by the user before saving to the db

 CurrentCustomer.RetailAccountCardsBindingList.Remove(racc);

不思議なことに、1. で発生するエラーは、RetailAccountCustomerCard の RetailAccountCustomerId プロパティに関する関係に問題があることを示しています。追加したCardオブジェクトとは関係ありません。新しいエンティティのオブジェクト プロパティを設定するだけで問題が発生するようです。

注意。例 1 は保存に関しては問題なく機能しますが、保存する前に新しいエンティティが削除された場合にのみ問題が発生します。

于 2009-01-20T00:42:29.580 に答える