4

提前为这个问题的长度道歉!

我有一个数据结构,从中创建了以下实体数据模型(表/字段重命名并简化了以便于理解!):

实体模型

PaymentMethod/ProductPaymentMethod结构的存在是因为 aCustomer可以有多个PaymentMethods可用的,但可以从它们中选择要使用的每个Product

,和都是基于 so 生成的,CustomerReference所以必须在初始保存后更新。ProductReferenceVendorReferenceCustomerId

ProductPaymentMethods需要PaymentMethodIdsso必须在初始Save之后添加。

ADO.NET Self-Tracking Entity Generator运行以生成自跟踪上下文和对象类。

CreateCustomer在 BLL 中有一个方法,它生成一个新实体,如下所示(伪代码):

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

返回值分配给CustomerBLL 中的新对象,并从 生成的引用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 xCurrency和 4 xFrequency记录 -UpdateCustomer正在接收标记为的实体Added

因此,经过一番研究,我在调用之前添加了以下内容UpdateCustomer

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

这停止了​​重复Customer,但我仍然被重复,Product并记录。VendorCurrencyFrequencyPaymentMethod

我想出的解决方案是遍历每个集合,并在调用之前将每个实体标记为未更改UpdateCustomer

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

Customer.PaymentMethods(对和重复Customer.Products.First().Frequencies

我现在没有重复,并且我的所有数据都已创建。

最后,关于我的问题!

我不禁觉得我在这里遗漏了一些东西。在每次更新之前,我是否真的必须检查关系树的每个部分并根据需要标记为已修改或未更改(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 使用 Private Accessor 调用 CustomerWCF.svc.cs

CustomerWCF.svc.cs 调用 CustomerBLL.cs

CustomerBLL.cs 调用 CustomerDAL.cs

DAL 参考模型

BLL 参考 DAL 和模型

服务参考 BLL 和模型

测试参考服务、BLL 和模型

我应该针对 ServiceReference 而不是 PrivateAccessor 进行测试吗?

4

1 回答 1

2

如果 EF 认为它是一个新对象,它将执行 Add,如果它认为它是一个现有对象,它将执行更新。

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

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

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

于 2011-05-20T18:19:30.390 回答