insert new object with children

Feb 9, 2010 at 5:04 AM
Edited Feb 9, 2010 at 5:13 AM

Hi I am having trouble inserting a new object with FK relational children using your class:

 

using (DataClassesDataContext dbcontext2 = new DataClassesDataContext())
            {
                dbcontext2.DeferredLoadingEnabled = false;
                SessionWrapper.order = new order();
//is the same as Session["order"] = new order();

                SessionWrapper.order.SetAsChangeTrackingRoot(EntityState.New);
                
                SessionWrapper.order.SetAsInsertOnSubmit(false);

                SessionWrapper.order.userModifiedID = SessionWrapper.userID;
                SessionWrapper.order.userCreatedID = SessionWrapper.userID;
                SessionWrapper.order.userCreatedFirstName = SessionWrapper.FirstName;
                SessionWrapper.order.userCreatedLastName = SessionWrapper.LastName;
                SessionWrapper.order.orderShipMultiShipment = false;
                SessionWrapper.order.orderShipPartShipment = false;
                SessionWrapper.order.customerID = SessionWrapper.customerID;
            }

 

the sessionwrapper method is just a wrapper class for the ASP.net session.

the orders properties and objects are added to over several asp.net pages. An order has one or more orderShipping entities (for multiple deliveries) and each orderShipping has one or more orderLines (productID and quantity).

I then try this:

 

using (DataClassesDataContext dbcontext2 = new DataClassesDataContext())
                    {
                        dbcontext2.DeferredLoadingEnabled = false;
                        SessionWrapper.order.SynchroniseWithDataContext(dbcontext2); //this line traverses all entities, attaching all of them as appropriate to the data context.

                        dbcontext2.SubmitChanges();
                    }

 

I receive this error:

An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.  This is not supported.

I have turned on uni-directional serialisation on the datacontext and have the abstract class installed.

if I null the orders orderShippings before submitting changes it inserts the order ok. Do I need to serialise/deserialise the order?

Can I suggest a simple ASP.net example without WCF?

Feb 9, 2010 at 12:17 PM

Hi,

Have you followed the 'Disconnected rules' on my blog? (see the link on the home tab under How to: Disconnected entities), You have set deferredloadingenabled = false, which is good - but you still need to either add a timestamp or set Update Check = false on all columns, have you got this done?

Also, you should not have to do SetAsInsertOnSubmit if you've already indicated it's a new object when settings as root, that should work - but wondering if it's confusing it.

I can't recall if it needs to be serialized, I don't think it does - you just have to make sure that you disconnect it properly and it should work - however It's been a while since I fiddle with it like that (I'm using WCF and serializing it), so I might be wrong - serialization may be needed.

I'll try and do a quick example tommorrow without serialization, let me know how you go.

Cheers

Matt

Feb 9, 2010 at 9:51 PM
Edited Feb 9, 2010 at 10:21 PM

I didnt have a timestamp column or set the update check to false. I added a timestamp column to all 3 tables and refreshed the context and still get the same error however. I also removed the SetAsInsertOnSubmit line. I think it needs to be serialised?

Also on each page that adds properties/entities to the order do i need to set the deferredloadingenabled = false?

Feb 10, 2010 at 8:47 AM

Hi Growls,

I tried this code and it worked fine (based on the database schema in the example that ships with LINQ2SQLEB)

            Customer customer;

            using (NorthWindDataContext db = new NorthWindDataContext())
            {
                TextWriter log = new StringWriter();
                db.Log = log;
                db.DeferredLoadingEnabled = false;
                customer = new Customer();
                customer.SetAsChangeTrackingRoot(EntityState.New);
                customer.CompanyName = "Test3";
                customer.CustomerID = "Test3";
                customer.Address = "Test3";
                DBLog = log.ToString();
            }


            // Update Order via root object, creating a new data context
            using (NorthWindDataContext db = new NorthWindDataContext())
            {
                TextWriter log = new StringWriter();

                db.Log = log;
                db.DeferredLoadingEnabled = false;
                customer.SynchroniseWithDataContext(db, true); //cascade delete                
                db.SubmitChanges();

                DBLog = log.ToString();
            }

Can you let me know what the relationships are - are the relationships going in the right direction - this would fail because it would assume that users are NEW objects rather than references? 

Cheers

Matt.

 

Apr 26, 2010 at 10:06 PM

Hi There,

on the entity being passed to the Save method above, can you check the LINQEntityState value for all entities involved (including children)?  If you are inserting records, it should be set to new. 

One thing that I thought of, If the "Submission" entity is being inserted in the case above, you need to use the extra parameter when setting it as the root object "SetAsChangeTracikingRoot", which indicates it's "New" initially.

Cheers

Matt.

Apr 27, 2010 at 12:16 PM

Hi there again,

You don't have to call SetAsChangeTrackingRoot(EntityState.Modified), to update entities, it will do this automatically if you modify the entity properties.  It's only when inserting a new entity from scratch you need to call SetAsChangeTrackingRoot(EntityState.New) as there is no easy way to tell if it's a new object or an existing object - so you have to tell it manually.

Cheers

Matt.