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

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

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

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

CustomerReference,ProductReference和VendorReference都是基于CustomerId生成的,因此必须在初始保存后更新.

ProductPaymentMethods需要PaymentMethodIds,因此必须在初始保存后添加.

已运行ADO.NET自跟踪实体生成器以生成自跟踪上下文和对象类.

我在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传递给DAL中的CreateCustomer方法,它执行以下操作:

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集合循环创建List< ProductPaymentMethod> productPaymentMethods使用PaymentMethodIds.然后添加:

savedCustomer.ProductPaymentMethods.Add(productPaymentMethods)

然后将newCustomer传递给DAL中的UpdateCustomer方法,该方法执行此操作:

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

然后将其返回到表示层

这导致重复创建并更新的所有内容 – 我最终得到2 x客户,2 x产品,2 x供应商,4 x PaymentMethod,4 x货币和4 x频率记录–UpdateCustomer正在接收实体标记为已添加

经过一些研究后,我在调用UpdateCustomer之前添加了以下内容:

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

这阻止了重复的客户,产品和供应商,但我仍然获得重复的货币,频率和PaymentMethod记录.

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

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

(对Customer.PaymentMethods和Customer.Products.First()重复.频率)

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

最后,关于我的问题!

我不禁觉得我在这里错过了一些东西.在每次更新之前,我是否真的必须检查关系树的每个部分并在必要时标记为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和Model

服务参考BLL和模型

测试参考服务,BLL和模型

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

最佳答案 如果它认为它是一个新对象,EF将执行添加,如果它认为它是现有的,则更新.

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

如果从数据库中获取对象,请更改值然后执行保存,EF知道它是现有对象并将执行更新.

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

点赞