如何停止自我跟踪实体执行添加而不是更新
为这个问题的长度提前道歉!如何停止自我跟踪实体执行添加而不是更新
我从以下Enity数据模型已经建立(表/字段重命名,并简化为便于理解!)的数据结构:
的PaymentMethod
/ProductPaymentMethod
结构的存在是因为一个Customer
可以有多个PaymentMethods
可用,但可以从中选择使用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
将退货分配给BLL中的新对象Customer
,并从CustomerId
生成参考并添加了:
savedCustomer.CustomerReference = generatedCustomerReference
savedCustomer.Products.First().ProductReference = generatedProductReference
savedCustomer.Products.First().Vendors.First().VendorReference = generatedVendorReference
savedCustomer.PaymentMethod
集合通过使用PaymentMethodIds
循环创建List<ProductPaymentMethod> productPaymentMethods
。这然后加入:
savedCustomer.ProductPaymentMethods.Add(productPaymentMethods)
newCustomer
然后被传递给UpdateCustomer
方法,其中行这DAL:
context.Customers.ApplyChanges(customer)
context.SaveChanges()
return customer
这然后返回到Presentation层
这导致的重复所有已经创建并更新的东西 - 我最终将以2 x Customer
,2 x Product
,2 x Vendor
,4 x PaymentMethod
,4 x Currency
个4×Frequency
记录 - UpdateCustomer
正在接受一个实体标记为Added
了一些研究所以之后我加入呼吁UpdateCustomer
之前执行以下操作:
savedCustomer.MarkAsModified()
savedCustomer.Products.First().MarkAsModified()
savedCustomer.Products.First().Vendors.First().MarkAsModified()
该停止复制Customer
,Product
和Vendor
但我仍然得到重复的Currency
,Frequency
和PaymentMethod
记录。
我想出了解决的办法是通过每个集合的循环,并呼吁UpdateCustomer
之前标记每个作为不变的entites的:现在
foreach (currency in Customer.Products.First().Currencies)
currency.MarkAsUnchanged()
(重复Customer.PaymentMethods
和Customer.Products.First().Frequencies
)
我不要重复,我的所有数据都会被创建。
最后,在我的问题!
我不禁觉得我在这里失去了一些东西。在每次更新之前,我是否真的必须检查关系树的每个部分,并根据需要标记为Modified或UnChanged(有Microsoft术语的完美混合)?
我认为术语“自我追踪”意味着所有应该自动处理。
这是使用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使用私有访问器ŧ O调用CustomerWCF.svc.cs
CustomerWCF.svc.cs调用CustomerBLL.cs
CustomerBLL.cs调用CustomerDAL.cs
DAL引用型号
BLL引用DAL和型号
服务参考BLL和型号
测试参考服务,BLL和型号
我应该根据ServiceReference而不是PrivateAccessor进行测试吗?
如果EF认为它是新对象,并且它认为它是现有对象,则EF将执行Add。
如果您在代码中使用new创建对象,则EF假定它是一个新对象。
如果您从数据库中获取对象,更改这些值然后进行保存,EF知道它是一个现有对象并将执行更新。
因此,如果您有一个已在代码中创建但可能存在于数据库中的对象,则必须先从数据库中检索它,然后进行更新并保存。
我发现这个资源很有用,正确设置了[STE's](http://skysigal.xact-solutions.com/Blog/tabid/427/entryid/2344/Default.aspx)。 – Menahem 2011-05-19 14:05:25
假设您使用WCF与客户端进行通信,您是否在生成WCF代理/引用时重用生成的STE类?如果没有,跟踪不会发生,但不会引发错误。 – Menahem 2011-05-19 14:08:43
目前我使用Visual Studio生成的私有访问器 – Shevek 2011-05-19 14:16:22