3

モデル#1-このモデルは、DevServerのデータベースにあります。 モデル#1 http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.png

モデル#2-このモデルはProd Serverのデータベースにあり、自動フィードによって毎日更新されます。 代替テキストhttp://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png

フィード(モデル#2)を作業中のDB(モデル#1)に同期するための簡単なコードを記述しました。これはプロトタイプコードであり、モデルが思ったほどきれいではない可能性があることに注意してください。また、フィードリンクデータ(主にClientID)のモデル#1への入力は、この時点では手動プロセスであるため、この単純な同期メソッドを作成しています。

private void SyncFeeds()
{
    var sourceList = from a in _dbFeed.Auto where a.Active == true select a;
    foreach (RivWorks.Model.NegotiationAutos.Auto source in sourceList)
    {
        var targetList = from a in _dbRiv.Product where a.alternateProductID == source.AutoID select a;
        if (targetList.Count() > 0)
        {
            // UPDATE...
            try
            {
                var product = targetList.First();
                product.alternateProductID = source.AutoID;
                product.isFromFeed = true;
                product.isDeleted = false;
                product.SKU = source.StockNumber;
                _dbRiv.SaveChanges();
            }
            catch (Exception ex)
            {
                string m = ex.Message;
            }
        }
        else
        {
            // INSERT...
            try
            {
                long clientID = source.Client.ClientID;
                var companyDetail = (from a in _dbRiv.AutoNegotiationDetails where a.ClientID == clientID select a).First();
                var company = companyDetail.Company;
                switch (companyDetail.FeedSourceTable.ToUpper())
                {
                    case "AUTO":
                        var product = new RivWorks.Model.Negotiation.Product();
                        product.alternateProductID = source.AutoID;
                        product.isFromFeed = true;
                        product.isDeleted = false;
                        product.SKU = source.StockNumber;
                        company.Product.Add(product);
                        break;
                }
                _dbRiv.SaveChanges();
            }
            catch (Exception ex)
            {
                string m = ex.Message;
            }
        }
    }
}

今質問のために:

  1. モデル#2では、Autoのクラス構造にClientIDがありません(赤い丸で囲まれた領域を参照)。これで、私が学んだことはすべて、EFがClientの子クラスを作成し、子クラスでClientIDを見つけることができるはずです。それでも、コードを実行すると、source.ClientはNULLオブジェクトになります。EFがやらないことを期待していますか?子クラスを正しく設定する方法はありますか?
  2. EFが親テーブルの子エンティティID(この場合はClientID)を非表示にするのはなぜですか?それを公開する方法はありますか?
  3. ことわざの親指の痛みのように他に何が突き出ていますか?

TIA

4

1 に答える 1

3

1)null forが表示されている理由source.Clientは、関連するオブジェクトは、要求するまでロードされないか、オブジェクトコンテキストにロードされるためです。以下はそれらを明示的にロードします:

if (!source.ClientReference.IsLoaded)
{
    source.ClientReference.Load();
}

Load()ただし、これは、呼び出しごとに1つのデータベースクエリを送信するため、複数のレコードのリストがある場合は最適ではありません。より良い代替手段はInclude()、最初のクエリのメソッドの代わりに、関心のある関連エンティティをロードするようにORMに指示することです。

var sourceList = from a in _dbFeed.Auto .Include("Client") where a.Active == true select a;

別の3番目の方法は、何か呼び出し関係の修正を使用することです。たとえば、たとえば、関連するクライアントが以前に照会された場合、それらは引き続きオブジェクトコンテキストにあります。例えば:

var clients = (from a in _dbFeed.Client select a).ToList();

次に、EFは関係を「修正」するため、source.Clientはになりませんnull。明らかに、これは同期のためにすべてのクライアントのリストが必要な場合にのみ行うことなので、特定の例には関係ありません。

オブジェクトを要求しない限り、オブジェクトがEFにロードされることはないことを常に覚えておいてください。

2) EFの最初のバージョンは、外部キーフィールドを監視可能なフィールドまたはプロパティに意図的にマップしていません。 これは問題の良い要約です。EF4.0では、一般的な需要により外部キーが公開されることを理解しています。

3)発生する可能性のある問題の1つは、ProductsまたはAutoNegotiationContactsが生成する可能性のあるデータベースクエリの数です。別の方法として、それらをまとめてロードするかjoin、最初のクエリでをロードすることを検討してください。

また、1つの「操作」にオブジェクトコンテキストを使用し、それを破棄することも、リクエスト間で永続化するのではなく、良い習慣と見なされています。1つを初期化する際のオーバーヘッドはほとんどないため、オブジェクトコンテキストごとに1つがよりSychFeeds()適切です。 ObjectContextを実装IDisposableしているので、usingブロックでインスタンス化し、メソッドの内容をその中でラップして、変更が送信されたらすべてが正しくクリーンアップされるようにすることができます。

于 2010-01-20T22:48:38.877 に答える