この質問の長さについて事前にお詫び申し上げます。
次のエンティティ データ モデルが作成されたデータ構造があります (テーブル/フィールドは名前が変更され、理解しやすいように簡略化されています)。
PaymentMethod
/ProductPaymentMethod
構造体が存在するのは、 a が複数の利用可能なものを持つことができるためですCustomer
がPaymentMethods
、 per を使用するものを選択できるからProduct
です。
、およびはすべてCustomerReference
に基づいて生成されるため、最初の保存後に更新する必要があります。ProductReference
VendorReference
CustomerId
その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)
newCustomer
CreateCustomer
次に、これを行う DAL のメソッドに渡されます。
context.Customers.AddObject(customer)
context.SaveChanges()
return customer
戻り値はCustomer
BLL 内の新しいオブジェクトに割り当てられ、参照は から生成され、CustomerId
追加されます。
savedCustomer.CustomerReference = generatedCustomerReference
savedCustomer.Products.First().ProductReference = generatedProductReference
savedCustomer.Products.First().Vendors.First().VendorReference = generatedVendorReference
を使用して作成するために、savedCustomer.PaymentMethod
コレクションがループされます。これが追加されます:List<ProductPaymentMethod> productPaymentMethods
PaymentMethodIds
savedCustomer.ProductPaymentMethods.Add(productPaymentMethods)
newCustomer
UpdateCustomer
次に、これを行う 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
、まだ複製され、レコードが取得されていました。Product
Vendor
Currency
Frequency
PaymentMethod
私が思いついた解決策は、各コレクションをループし、呼び出す前に各エンティティを未変更としてマークすることでした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 に対してテストする必要がありますか?