4

この質問の長さについて事前にお詫び申し上げます。

次のエンティティ データ モデルが作成されたデータ構造があります (テーブル/フィールドは名前が変更され、理解しやすいように簡略化されています)。

エンティティ モデル

PaymentMethod/ProductPaymentMethod構造体が存在するのは、 a が複数の利用可能なものを持つことができるためですCustomerPaymentMethods、 per を使用するものを選択できるからProductです。

、およびはすべてCustomerReferenceに基づいて生成されるため、最初の保存後に更新する必要があります。ProductReferenceVendorReferenceCustomerId

そのProductPaymentMethods必要性はPaymentMethodIds、最初の保存後に追加する必要があります。

ADO.NET Self-Tracking Entity Generatorが実行され、自己追跡コンテキストとオブジェクト クラスが生成されました。

次のように新しいエンティティを生成する BLLにCreateCustomerメソッドがあります (疑似コード):

Customer newCustomer = new Customer()
Product newProduct = new Product()
Vendor newVendor = new Vendor()
List<Currency> newCurrencies = new List<Currency> { new Currency(), new Currency() }
List<Frequency> newFrequencies = new List<Frequency> { new Frequency(), new Frequency() }
List<PaymentMethod> newPaymentMethods = new List<PaymentMethod> { new PaymentMethod(), new PaymentMethod() }
newProduct.Vendors.Add(newVendor)
newProduct.Currencies.Add(newCurrencies)
newProduct.Frequencies.Add(newFrequencies)
newCustomer.Products.Add(newProduct)
newCustomer.PaymentMethods.Add(newPaymentMethods)

newCustomerCreateCustomer次に、これを行う DAL のメソッドに渡されます。

context.Customers.AddObject(customer)
context.SaveChanges()
return customer

戻り値はCustomerBLL 内の新しいオブジェクトに割り当てられ、参照は から生成され、CustomerId追加されます。

savedCustomer.CustomerReference = generatedCustomerReference
savedCustomer.Products.First().ProductReference = generatedProductReference
savedCustomer.Products.First().Vendors.First().VendorReference = generatedVendorReference

を使用して作成するために、savedCustomer.PaymentMethodコレクションがループされます。これが追加されます:List<ProductPaymentMethod> productPaymentMethodsPaymentMethodIds

savedCustomer.ProductPaymentMethods.Add(productPaymentMethods)

newCustomerUpdateCustomer次に、これを行う DAL のメソッドに渡されます。

context.Customers.ApplyChanges(customer)
context.SaveChanges()
return customer

これはプレゼンテーション層に戻されます

これにより、作成されてから更新されたすべての複製が作成されました-2 x Customer、2 x Product、2 x Vendor、4 x PaymentMethod、4 x Currency、および 4 xFrequencyレコードになります-UpdateCustomerとしてマークされたエンティティを受け取っていましたAdded

そのため、少し調査した後、呼び出す前に次を追加しましたUpdateCustomer

savedCustomer.MarkAsModified()
savedCustomer.Products.First().MarkAsModified()
savedCustomer.Products.First().Vendors.First().MarkAsModified()

これにより、複製されたが停止しましたがCustomer、まだ複製され、レコードが取得されていました。ProductVendorCurrencyFrequencyPaymentMethod

私が思いついた解決策は、各コレクションをループし、呼び出す前に各エンティティを未変更としてマークすることでしたUpdateCustomer:

foreach (currency in Customer.Products.First().Currencies)
    currency.MarkAsUnchanged()

Customer.PaymentMethods(とについて繰り返すCustomer.Products.First().Frequencies)

重複がなくなり、すべてのデータが作成されました。

最後に、私の質問に進みます!

ここで何かが欠けていると感じずにはいられません。リレーションシップ ツリーの各部分をチェックし、必要に応じてすべての更新の前に Modified または UnChanged としてマークする必要がありますか?

「自己追跡」という用語は、すべてが自動的に処理される必要があることを意味すると思いました。

これはEF / STEを使用する正しい方法ですか、それともより良い方法がありますか?

編集: 私の Visual Studio ソリューションに関するもう少しの情報。

DAL プロジェクト - CustomerModel.edmx、CustomerModel.Context.tt、CustomerDAL.cs

モデル プロジェクト - CustomerModel.tt

BLL プロジェクト - CustomerBLL.cs

WCF プロジェクト - CustomerWCF.svc.cs

テスト プロジェクト CustomerTest.cs

CustomerTest.cs は Private Accessor を使用して CustomerWCF.svc.cs を呼び出します

CustomerWCF.svc.cs が CustomerBLL.cs を呼び出す

CustomerBLL.cs が CustomerDAL.cs を呼び出す

DAL 参照モデル

BLL は DAL とモデルを参照します

サービス参照 BLL とモデル

テスト参照サービス、BLL、およびモデル

PrivateAccessor ではなく ServiceReference に対してテストする必要がありますか?

4

1 に答える 1

2

EF は、新しいオブジェクトであると判断した場合は追加を実行し、既存のオブジェクトであると判断した場合は更新します。

new ... を使用してコードでオブジェクトを作成すると、EF はそれが新しいオブジェクトであると想定します。

データベースからオブジェクトを取得し、値を変更してから保存すると、EF はそれが既存のオブジェクトであることを認識し、更新を行います。

したがって、コードで作成されたオブジェクトがデータベースに存在する可能性がある場合は、最初にデータベースから取得し、更新してから保存する必要があります。

于 2011-05-20T18:19:30.390 に答える