如何停止自我跟踪实体执行添加而不是更新

问题描述:

为这个问题的长度提前道歉!如何停止自我跟踪实体执行添加而不是更新

我从以下Enity数据模型已经建立(表/字段重命名,并简化为便于理解!)的数据结构:

Entity Model

PaymentMethod/ProductPaymentMethod结构的存在是因为一个Customer可以有多个PaymentMethods可用,但可以从中选择使用Product

CustomerReference,ProductReferenceVendorReference都是基于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() 

该停止复制CustomerProductVendor但我仍然得到重复的Currency,FrequencyPaymentMethod记录。

我想出了解决的办法是通过每个集合的循环,并呼吁UpdateCustomer之前标记每个作为不变的entites的:现在

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

(重复Customer.PaymentMethodsCustomer.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进行测试吗?

+0

我发现这个资源很有用,正确设置了[STE's](http://skysigal.xact-solutions.com/Blog/tabid/427/entryid/2344/Default.aspx)。 – Menahem 2011-05-19 14:05:25

+0

假设您使用WCF与客户端进行通信,您是否在生成WCF代理/引用时重用生成的STE类?如果没有,跟踪不会发生,但不会引发错误。 – Menahem 2011-05-19 14:08:43

+0

目前我使用Visual Studio生成的私有访问器 – Shevek 2011-05-19 14:16:22

如果EF认为它是新对象,并且它认为它是现有对象,则EF将执行Add。

如果您在代码中使用new创建对象,则EF假定它是一个新对象。

如果您从数据库中获取对象,更改这些值然后进行保存,EF知道它是一个现有对象并将执行更新。

因此,如果您有一个已在代码中创建但可能存在于数据库中的对象,则必须先从数据库中检索它,然后进行更新并保存。

+0

这只有在保存和更新在相同上下文下执行时才有效。 – Shevek 2011-05-23 09:40:10

+0

保存和更新发生在DAL中,每个人都有自己的上下文。我该如何处理?上下文是否应该在BLL中创建并传递给DAL,以便Save和Update都可以使用它? – Shevek 2011-05-23 09:42:53

+0

我在BLL中创建了上下文并传递给了DAL中的创建和更新方法 - 这是有效的!非常感谢 – Shevek 2011-05-23 10:39:44