0

Okay, so it's late and I'm tired, but this shouldn't be happening... or so I believe. I have the following code for an event handler for a button click where I create a new customer from a web form.

int customerId = <from_somewhere_doesnt_matter>;
Customer cust;

if (int.TryParse(Request.QueryString["cid"], out customerId)) {
    // update existing customer
    cus = db.Customers.Single(c => c.CustomerId == customerId);
    cus.UpdatedByUser = user;
    cus.Updated = DateTime.Now;
    }
else {
    // create new customer
    cus = new Customer();
    cus.InsertedByUser = user;
    cus.Inserted = DateTime.Now;
}

SetFields(cus);
db.SaveChanges();

The SetFields() method just populates the different properties for the customer from the corresponding web form fields.

I have been running this code in production for quite a while and it's been working fine. However, recently a user told me it doesn't work to add a new user (doesn't happen very often). I checked it, and sure enough, I filled in the form and tried to add the user but was just redirected back to the user list without any error message and without a new user.

I checked the code, and realised I had forgotten to add the db.Users.AddObject(usr) when adding a new user. I added the method call, and the user was added correctly. I then went to the customer code, just to check how and when I call the AddObject-method there, and it turns out I don't!

I might be blind, but I have searched the source code and I do not call the method anywhere and it still works to add a customer! The only thing I can think of is that the customer is added because it refers to another object (the current user), and that somehow triggers an add. The user does not depend on any other fields.

What is happening!?

Thanks in advance!

joscarsson
  • 4,789
  • 4
  • 35
  • 43

2 Answers2

0

When you set

cus.InsertedByUser = user;

Your customer will be added to the user.Customers collection that represents the other end of the many-to-one. This gives EF a handle on the object which will then be added to the context and saved away since it is new.

Chris Sainty
  • 9,086
  • 1
  • 26
  • 31
  • Apparently I can only mark one answer as the correct answer, even if this is correct as welll :) Thanks for the reply! – joscarsson Jul 11 '11 at 19:23
0

The reason might be automatic association fixup. The T4 Template POCO Generator of EF 4.0 for instance creates such methods which are called in the property setters. Possibly it happens in this line in your code:

cus.InsertedByUser = user;

If your User entity has a collection of customers (as the inverse navigation property to InsertedByUser) then the POCO Generator would create a fixup method which does something like ...

InsertedByUser.Customers.Add(this);

... where this is cus in your example. This is called in the setter for the InsertedByUser property. This means that your new created customer cus is automatically added to the Customers collection of the user which you assign. EF change detection will recognize this and put the new customer in Added state into the context. When you call SaveChanges a new customer record in the database is created.

Just a hypothesis. You could check in detail what's going on by debugging into the property setter.

Slauma
  • 175,098
  • 59
  • 401
  • 420