4

外部ソースからデータを xml としてロードしています。データは逆シリアル化され、オブジェクトをループ処理してドメイン エンティティに注ぎ込みます。

データ間の関係を作成し、データベース呼び出しを削減するために、アイテムが見つからない場合は最初に DbSet.Local からアイテムを取得しようとする拡張メソッドを作成し、次に示すように DbSet.SingleOrDefault() を使用してデータベースをクエリします。 .

public static TEntity SingleOrDefaultLocalFirst<TEntity>(this IDbSet<TEntity> set,
        Func<TEntity, bool> predicate) where TEntity : class
    {
        if (set == null)
            throw new ArgumentNullException("set");
        if (predicate == null)
            throw new ArgumentNullException("predicate");

        TEntity results = null;

        try
        {
            results = set.Local.SingleOrDefault(predicate);
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.Message, "Error");
        }

        if (results != null)
        {
            return results;
        }
        return set.SingleOrDefault(predicate);
    }

try catch ブロックは、修正しようとしている問題を抑制するためにあります。

何らかの理由で、ローカル ストアをクエリするときのナビゲーション プロパティが設定されていません。したがって、次のようなものを使用すると

(x=>x.Participant.Event.ExternalId==newItem.Id)

私のラムダとして、参加者の nav プロパティは null です。

このコードで常に null 参照エラーが発生しないようにする方法が必要だと思います。

ループが使用を開始する前に、データベースから参加者とイベントのデータを明示的にロードしようとしました

context.Participant.Load()

しかし、これは違いはありません。

ナビゲーション プロパティが null である理由と、それらを最も効率的に設定する方法を誰か教えてもらえますか?

そして、なぜ私が Find() を使用しないのか不思議に思っている人がいれば、それは、外部データが多くのプロパティと、私のシステムの主キーではない外部 ID フィールドにキー付けされているためです。

アップデート:

実際のコードを含めるのに時間をかけるつもりはありません。使用可能な例に絞り込むには多すぎるため、Customer/Order/OrderItem の典型的な例を使用してみます。

本当の問題は、ネストされたエンティティがあり、次のようなものを使用して存在を確認しようとする場合です。

var orderLine = context.OrderLineItems.Local.SingleOrDefault(x=>x.Order.Number == 1234)

これを使用する前に、Orders と Customers がコンテキストに明示的に読み込まれている場合でも、Order の nullreference エラーがスローされます。

context.Orders.Load()

しかし、これを行うと:

var orderLine = context.OrderLineItems.SingleOrDefault(x=>x.Order.Number == 1234)

それが動作します。

Local を呼び出すときに機能しない理由を理解したい。関連する nav プロパティが既にコンテキストに読み込まれているのに、データベースにアクセスして関連するプロパティを取得する必要があるのはなぜですか? または私は何かを逃していますか?

4

2 に答える 2

0

ここでの問題は、「デシリアライズ」したオブジェクトがプロキシされていないことです。

から項目を取得する場合DbSet<T>、Entity Framework は 型のオブジェクトを提供しませんT。代わりに、関連プロパティTProxyである新しいクラスを作成します。overridesそうすればget、プロパティを取得すると、Entity Framework が認識し、呼び出しをインターセプトできます。

オブジェクトを Entity Framework の外部で逆シリアル化することにより、遅延読み込みに必要な "フック" をゲッターに追加する機会がありません。そのため、オブジェクトのプロパティで get を呼び出すと、EF は遅延読み込みを行いません。

これに対する解決策は、Entity Framework を使用してすべてのオブジェクトをインスタンスT化し、これらのオブジェクトに逆シリアル化してからアタッチすることです。

DbSet<T> set = ...;
T item = set.Create();
T deserialized = Deserialize(..);
AutoMapper.Map(deserialized, item);
set.Attach(item);
于 2014-07-10T18:26:24.637 に答える