1

おそらく、元の質問は長すぎて不要な詳細が多すぎると思うので、これは単純化するための私の試みです。

以下のアクションのいずれかを実行する手段を探しています。すべてではなく、1つだけ実行する必要があります。これらのいずれかに対する答えを誰かが知っている場合は、応答してください。したがって、LinqtoSQLで次のいずれかを実行することは可能ですか。

  • それらのエンティティを追跡するかどうかにかかわらず、エンティティをDataContextビアから引き出しますか?ExecuteQueryExecuteMethodCall

  • それらのエンティティがすでに取得されており、IDキャッシュにすでに存在している場合でも、データベースから取得した結果の新しいコピーを常に呼び出すExecuteQueryか、保証しますか?ExecuteMethodCall

  • 特定のエンティティタイプで変更追跡を実行しないようにLinqtoSQLに指示しますが、他のタイプの変更追跡は許可しますか?

制限:

  • このRefresh方法は問題外です。エンティティの数は非常に多く、これはパフォーマンスの障害になります。

  • クエリの実行後にに戻すことはできないため、単純にに設定することはできません。また、ObjectTrackingEnabled一部エンティティを追跡する必要があります。falseDataContexttrue

  • また、オリジナルを捨ててDataContext新しいものを使用することもできません。トランザクションの途中でこれを実行できる必要があります。


これは深刻な問題になり始めており、デフォルトの動作はよく考えられていないと思います。アドホッククエリまたはストアドプロシージャを実行すると、受け取る結果は、そのクエリによって返された正確な結果になると思います。それは理にかなっているだけです。古い、古いエンティティが必要な場合、なぜデータベースに戻ってそれらを取得するのでしょうか。

現時点での回避策は、(a)DataContextクエリ用に特別に新しいものを作成し、トランザクション分離レベルをオーバーライドするか、(b)リターンタイプをすべての点でエンティティと同一であるが、[Table]属性を作成し、AutoMapperを使用して元のエンティティにマップします。これらは両方とも恐ろしいハックのようです。

この難問について誰かが持っている提案を本当に感謝します。

4

2 に答える 2

3

私はこの問題の実行可能な長期的な回避策を思い付くことができました。それは完全に理想的ではありませんが、これまでのところ採用するのは比較的苦痛がなく、他の方法よりもはるかに怖いものではありません。

これらのクエリはとにかく純粋なSQLであるExecuteQueryため、すべてインラインSQLまたはストアドプロシージャ用です。特定のエンティティについて知りExecuteMethodCallたくない場合は、インスタンスの「生の」ADO.NETにドロップダウンすることにしました。DataContext

もちろん、からのIDbCommandインスタンスと手動マッピングの束を処理しなければならないのは恐ろしいことIDataReaderです。そのため、今朝、ライブラリをコーディングして、手間のかかる作業のほとんどを実行し、「流暢」なものを公開するために数時間を費やしました(Iのラッパーという用語を大まかに使用します。これは、既存のエンティティを変更せずに使用できるようにIDbCommandする自動、およびより単純なクエリをすばやく作成できるようにするためのオーバーロードされた拡張メソッドの束です。LinqDataReaderMapperMetaModel

一日の終わりに、私は次のようなものを書いています:

var results = context.Connection
    .Command("SELECT Column1, Column2 FROM Table " +
             "WHERE FilterColumn1 = @Param1 AND FilterColumn2 = @Param2")
    .Parameters(
        p => p.Name("Param1").Value(someValue),
        p => p.Name("Param2").Value(someOtherValue))
    .ExecuteReader()
    .MapWith(context.Mapping).To<MyEntity>();

またはこれだけ:

var results = context
    .ExecuteQueryRaw<MyEntity>(CommandType.StoredProcedure, "SomeProc",
        new { Param1 = someValue, Param2 = someOtherValue });

コード全体を投稿するつもりはありません-かなり長く、この時点では大きなtl; drになると思います-しかし、主なアイデアは、これらの両方が私にを返すというIEnumerable<MyEntity>ことです、そしてそれらはから直接コピーされているためIDataReader、本質的に切り離されたエンティティです。は、それらをDataContext直接認識していないため、結果を傍受したり、事後に追跡したりすることはできません。

DataContextしたがって、問題は部分的に解決されましたが、それ自体を動作させることができれば、それでもなお良いでしょう。

于 2010-02-05T20:55:54.363 に答える
0

LINQクエリから結果の新しいオブジェクトを作成する場合、変更は追跡されません。したがって、既存のDataContextを使用して、更新する必要がないことがわかっている値をロードできます(ここからのコード)。

using (NorthwindDataContext context = new NorthwindDataContext())
{
  var a = from c in context.Categories
  select new Category
  {
    CategoryID = c.CategoryID,
    CategoryName = c.CategoryName,
    Description = c.Description
  };
}

これは基本的に、回答の2番目の例にあるものだと思います。これは機能し、悪い考えではないことを確認したいと思います。

また、私の理解では、どのような場合でも単一の大規模なDataContextを使用するべきではありません。DataContextは、実際には作業単位レベルのコレクションであり、全世界ではありません。したがって、読み取り専用タイプのデータと更新可能なデータに別々のDataContextを使用することは、完全に理にかなっています(どちらが事前に予測できない場合を除きます)。

于 2010-02-05T21:09:32.590 に答える