Sorry in advance for the length of this question!
I have a data structure from which the following Enti data model was created (tables / fields renamed and simplified for ease of understanding!):

The structure of ProductPaymentMethod / ProductPaymentMethod exists, because Customer can have several PaymentMethods , but can choose from them which should be used for Product .
CustomerReference , ProductReference and VendorReference are created based on CustomerId , so they need to be updated after the initial save.
ProductPaymentMethods requires ProductPaymentMethods , so you need to add it after the initial save.
ADO.NET Self-Tracking Entity Generator to generate self ADO.NET Self-Tracking Entity Generator contexts and object classes.
I have a CreateCustomer method in the BLL that generates a new Entity as follows (psuedo-code):
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 then passed to the CreateCustomer method in the DAL, which does the following:
context.Customers.AddObject(customer) context.SaveChanges() return customer
A return is assigned to the new Customer object in the BLL and the links generated from CustomerId , and added:
savedCustomer.CustomerReference = generatedCustomerReference savedCustomer.Products.First().ProductReference = generatedProductReference savedCustomer.Products.First().Vendors.First().VendorReference = generatedVendorReference
The savedCustomer.PaymentMethod collection loops to create a List<ProductPaymentMethod> productPaymentMethods using PaymentMethodIds . Then added:
savedCustomer.ProductPaymentMethods.Add(productPaymentMethods)
newCustomer then passed to the UpdateCustomer method in the DAL, which does this:
context.Customers.ApplyChanges(customer) context.SaveChanges() return customer
He then returns to the presentation level.
This led to duplication of everything that was created and then updated - I get 2 x Customer , 2 x Product , 2 x Vendor , 4 x PaymentMethod , 4 x Currency and 4 x Frequency entries - UpdateCustomer received the object marked as Added
So, after a little research, I added the following before calling UpdateCustomer :
savedCustomer.MarkAsModified() savedCustomer.Products.First().MarkAsModified() savedCustomer.Products.First().Vendors.First().MarkAsModified()
This stopped duplicate Customer , Product and Vendor , but I still got duplicate Currency , Frequency and PaymentMethod records.
The solution I came across was to scroll through each collection and mark each of the names as immutable before calling UpdateCustomer :
foreach (currency in Customer.Products.First().Currencies) currency.MarkAsUnchanged()
(repeated for Customer.PaymentMethods and Customer.Products.First().Frequencies )
Now I do not get duplication, and all my data is created.
Finally to my question!
I cannot help but feel that something is missing here. Do I need to check every part of the relationship tree and mark it as Modified or UnChanged (Microsoft has a wonderful mixture of terms!) As necessary before each update?
I thought the term "Self-Tracking" means that all this should be processed automatically.
Is this the right way to use EF / STE or is there a better way?
EDIT: A little more information about my Visual Studio solution.
DAL project - CustomerModel.edmx, CustomerModel.Context.tt and CustomerDAL.cs
Model project - CustomerModel.tt
BLL Project - CustomerBLL.cs
WCF Project - CustomerWCF.svc.cs
CustomerTest.cs Testing Project
CustomerTest.cs uses Private Accessor to call CustomerWCF.svc.cs
CustomerWCF.svc.cs calls CustomerBLL.cs
CustomerBLL.cs calls CustomerDAL.cs
Links DAL Model
BLL DAL and Model Links
Service Links BLL and Model
Test, Service, BLL, and Model Test Links
Should I test ServiceReference instead of PrivateAccessor?