21

LINQ to SQL をデバッグして変更を送信するのに非常に苦労しています。

私はhttp://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspxを使用しています。これは単純なクエリのデバッグに最適です。

私は自分のアプリケーションから次のスニペットを使用して、プロジェクトの DataContext クラスで作業しています。

JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.SubmitChanges();

this.SubmitChanges; を実行すると、非常に奇妙な例外が発生します。

Index was outside the bounds of the array.

スタック トレースは、私が踏み込めない場所に移動します。

at System.Data.Linq.IdentityManager.StandardIdentityManager.MultiKeyManager`3.TryCreateKeyFromValues(Object[] values, MultiKey`2& k)
   at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache`2.Find(Object[] keyValues)
   at System.Data.Linq.IdentityManager.StandardIdentityManager.Find(MetaType type, Object[] keyValues)
   at System.Data.Linq.CommonDataServices.GetCachedObject(MetaType type, Object[] keyValues)
   at System.Data.Linq.ChangeProcessor.GetOtherItem(MetaAssociation assoc, Object instance)
   at System.Data.Linq.ChangeProcessor.BuildEdgeMaps()
   at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
   at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
   at System.Data.Linq.DataContext.SubmitChanges()
   at JobTrakDataContext.CreateNewJob(NewJob job, String userName) in D:\JobTrakDataContext.cs:line 1119

誰かが使用するツールやテクニックを持っていますか? 簡単なものがありませんか?

編集: Slace の提案を使用して .net デバッグをセットアップしましたが、.net 3.5 コードはまだ利用できません: http://referencesource.microsoft.com/netframework.aspx

EDIT2 : sirroccoの提案に従って InsertOnSubmit に変更しましたが、それでも同じエラーが発生します。

EDIT3: 生成された SQL をログに記録し、ChangeExceptoinException をキャッチしようとする Sam の提案を実装しました。これらの提案はこれ以上光を当てません。例外がスローされたときに実際に SQL を生成することはありません。

EDIT4: 以下で私に合った答えを見つけました。単なる理論ですが、現在の問題は修正されました。

4

19 に答える 19

32

SubmitChanges() メソッドで DataContext に送信される変更内容を正確に把握することは、常に役に立ちます。

DataContext.GetChangeSet()メソッドを使用すると、追加、変更、または削除されたオブジェクトの 3 つの読み取り専用 IList を保持するChangeSetオブジェクト インスタンスが返されます。

SubmitChanges メソッド呼び出しの直前にブレークポイントを配置し、以下を含むウォッチ (またはクイック ウォッチ) を追加できます。

ctx.GetChangeSet();

ctx が DataContext の現在のインスタンスである場合、SubmitChanges 呼び出しで有効になるすべての変更を追跡できます。

于 2009-04-01T20:59:51.850 に答える
8

まず、助けてくれてありがとう、ついに見つけました。

解決策は、プロジェクトから .dbml ファイルを削除し、空の .dbml ファイルを追加して、「サーバー エクスプローラー」からプロジェクトに必要なテーブルを再設定することでした。

これを行っているときに、いくつかのことに気付きました。

  • システムには、「Job Master」など、2 つの単語と単語の間にスペースが入った名前のテーブルがいくつかあります。そのテーブルを .dbml ファイルに戻すと、「Job_Master」というテーブルが作成され、スペースがアンダースコアに置き換えられます。
  • 元の .dbml ファイルでは、私の開発者の 1 人が .dbml ファイルを調べてすべてのアンダースコアを削除したため、.dbml ファイルでは「Job_Master」が「JobMaster」になります。コードでは、より標準的な命名規則でテーブルを参照できます。
  • 私の理論では、投影を行っている間に「JobMaster」から「Job Master」への変換がどこかで失われ、配列の範囲外エラーが発生し続けました。

それは単なる理論です。誰かがそれをよりよく説明できるなら、ここで具体的な答えが欲しいです。

于 2008-09-19T18:27:27.640 に答える
6

私の最初のデバッグ アクションは、生成された SQL を確認することです。

JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.Log = Console.Out; // prints the SQL to the debug console
this.SubmitChanges();

2 つ目は、ChangeConflictException をキャプチャして、失敗の詳細を確認することです。

  catch (ChangeConflictException e)
  {
    Console.WriteLine("Optimistic concurrency error.");
    Console.WriteLine(e.Message);
    Console.ReadLine();
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
      MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType());
      Customer entityInConflict = (Customer)occ.Object;
      Console.WriteLine("Table name: {0}", metatable.TableName);
      Console.Write("Customer ID: ");
      Console.WriteLine(entityInConflict.CustomerID);
      foreach (MemberChangeConflict mcc in occ.MemberConflicts)
      {
        object currVal = mcc.CurrentValue;
        object origVal = mcc.OriginalValue;
        object databaseVal = mcc.DatabaseValue;
        MemberInfo mi = mcc.Member;
        Console.WriteLine("Member: {0}", mi.Name);
        Console.WriteLine("current value: {0}", currVal);
        Console.WriteLine("original value: {0}", origVal);
        Console.WriteLine("database value: {0}", databaseVal);
      }
    }
  }
于 2008-09-18T10:35:32.503 に答える
4

DataContext の部分クラスを作成し、Created または what have you partial メソッドを使用して、#if DEBUG でラップされた console.out にログをセットアップできます。これにより、インスタンスのデバッグ中に実行されたクエリを確認できます。使用しているデータコンテキスト。

LINQ to SQL の例外をデバッグしているときに、これが役立つことがわかりました。

partial void OnCreated()
{
#if DEBUG
      this.Log = Console.Out;
#endif
}
于 2008-09-18T04:30:34.800 に答える
2

これは私がしたことです

...
var builder = new StringBuilder();
try
{
    context.Log = new StringWriter(builder);
    context.MY_TABLE.InsertAllOnSubmit(someData);
    context.SubmitChanges();                
}
finally
{
    Log.InfoFormat("Some meaningful message here... ={0}", builder);
}
于 2012-07-17T19:46:09.693 に答える
2

上記のエラーは通常、関連付けが間違った方向を指しているために発生します。データ モデリング ツールと比較すると、L2S デザイナーの関連付け矢印が後方を指しているため、手動で関連付けをデザイナーに追加すると、これは非常に簡単に発生します。

彼らがもっと説明的な例外を投げたらいいのですが、おそらく将来のバージョンでそうなるでしょう。(ダミアン/マット...?)

于 2008-09-18T03:28:46.150 に答える
1

VS 2008 には、.NET フレームワーク ( http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code .aspx )

これはおそらく最善の策です。正確な時点で何が起こっているか、すべてのプロパティが何であるかを確認できます

于 2008-09-17T22:47:52.550 に答える
1

新しいインスタンスで UpdateJobMaster を実行するのはなぜですか? InsertOnSubmit ではないでしょうか。

JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.InsertOnSubmit(newJobToCreate);
this.SubmitChanges();
于 2008-09-18T04:26:08.943 に答える
1

これはほぼ確実にすべての人の根本的な原因ではありませんが、私のプロジェクトでこれとまったく同じ例外が発生しました。根本的な原因は、エンティティ クラスの構築中に例外がスローされたことであることがわかりました。奇妙なことに、真の例外は「失われ」、代わりに、オブジェクトを取得する Linq ステートメントの反復子で発生する ArgumentOutOfRange 例外として現れます。

このエラーが発生し、POCO に OnCreated または OnLoaded メソッドを導入している場合は、それらのメソッドをステップ実行してみてください。

于 2009-08-04T18:01:10.307 に答える
1

簡単な解決策は、データベースでトレースを実行し、それに対して実行されたクエリを検査することです。もちろん、データベースにアクセスする他のアプリケーションなどを整理するためにフィルター処理されます。

もちろん、例外を乗り越えた場合にのみ役立ちます...

于 2008-09-17T19:29:24.053 に答える
0

私は最近同じ問題に遭遇しました:私がしたことは

Proce proces = unit.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
                                                                         where pt.Name == "Fix-O"
                                                                         select pt).Single().ProcesTypeId &&
                                                                      u.UnitId == UnitId);

それ以外の:

Proce proces = context.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
                                                                     where pt.Name == "Fix-O"
                                                                     select pt).Single().ProcesTypeId &&
                                                                  u.UnitId == UnitId);

コンテキストが明らかにDataContextオブジェクトであり、「unit」がUnitオブジェクトのインスタンスである場合、dbmlファイルのデータクラスです。

次に、「proce」オブジェクトを使用して、別のデータクラスオブジェクトのインスタンスにプロパティを設定しました。おそらく、LINQエンジンは、「proce」オブジェクトから設定したプロパティが、他のデータクラスオブジェクトをデータベースに追加するためにLINQによって作成される必要があるINSERTコマンドで許可されているかどうかを確認できませんでした。

于 2009-03-20T08:42:54.120 に答える
0

うーん。

WAG(Wild Ass Guess)を使用すると、LINQのように見えます-SQLは、JobMasterクラスの作成に基づいて、存在しないIDを持つオブジェクトを見つけようとしています。LINQ to SQLが存在しない可能性のあるクラスのインスタンスをフェッチしようとするような、そのテーブルに関連する外部キーはありますか?新しいオブジェクトのProjectIDを文字列に設定しているようです-本当に文字列のIDを持っていますか?新しいプロジェクトに設定しようとしている場合は、新しいプロジェクトを作成してそのIDを取得する必要があります。

最後に、UpdateJobMasterは何をしますか?上記が当てはまるようなことをしているのでしょうか?

于 2008-09-17T19:49:43.867 に答える
0

今日、同様の質問をここに投稿しました: Strange LINQ Exception (Index out of bounds)

これは別の使用例です。このバグは SubmitChanges() の実行中に発生し、私の場合は単純なクエリの実行中に発生しますが、Index out of range エラーでもあります。

質問のデータの組み合わせがサマリア人の良い回答に役立つ場合に備えて、この質問に相互投稿してください:)

于 2008-10-10T19:38:24.533 に答える
0

LINQ ChangeConflictException をデバッグしようとしたときに、この質問に行き着きました。最終的に、DBML ファイルのテーブルにプロパティを手動で追加したことが問題であることに気付きましたが、 Nullable (私の場合は true であったはずです) やServer Data Typeなどのプロパティを設定するのを忘れていました。

これが誰かに役立つことを願っています。

于 2016-07-22T12:07:26.977 に答える
0

SO# 237415への回答で、この例外に関する私の経験を投稿しました

于 2009-06-05T01:22:57.417 に答える
0

大規模なプロジェクトで Linq to SQL デザイナーを実際に使用するのをやめましたが、この問題が主な理由の 1 つです。また、名前、データ型、関係の多くのデフォルト値を変更しましたが、デザイナーがそれらの変更を失うこともありました。正確な理由を見つけたことがなく、確実に再現することはできません。

それは、他の制限とともに、デザイナーをやめて手作業でクラスを設計する原因となりました。パターンに慣れてしまえば、実はデザイナーよりも簡単です。

于 2008-10-10T17:07:09.953 に答える
0

dbml 内のすべての「主キー」列が実際にデータベース テーブルの主キーに関連付けられていることを確認してください。設計者が追加の PK 列を dbml に配置することを決定した状況がありました。これは、保存時に LINQ to SQL が外部キーの両側を見つけることができなかったことを意味します。

于 2009-02-10T10:15:29.853 に答える