5

Background: i have a 1 to 0..1 relationship between User and UserSettings.

The important part of the model is as follows:

public class User
{
   public int UserId { get; set; }
   public string Name { get; set; }
   public UserSettings Settings { get; set; }
}

public class UserSettings
{
   public int UserId { get; set; } // PK/FK
   public sting SpecialField { get; set; }
}

When i do an INSERT:

var user = new User { Settings = new UserSettings { SpecialField = "Foo" }};
ctx.Users.Add(user);
ctx.SaveChanges();

Everything is cool, when i check the trace, User is added first, then the UserSettings - as you would expect, since UserSettings needs the IDENTITY from User.

But when i UPDATE that "SpecialField":

var user = ctx.Users.Include("Settings").Single();
user.Name = "Joe";
user.Settings.SpecialField = "Bar";
ctx.SaveChanges();

I see that the trace shows EF updating the UserSettings first, then the User.

Why?

This is important for me, because i have trigger logic that needs to execute only when SpecialField is changed, and it needs to reference data on User.

Can anyone explain this behaviour? Is there a workaround (other than a hack - which would involve me manually "touching" special field again, which is really bad).

RPM1984
  • 72,246
  • 58
  • 225
  • 350
  • A workaround that comes to mind would be adding a call to `SaveChanges()` after changing `user.Name`. And a sidenote: if you are using EF 4.1 (according to the tag), it's better to use `Include(u => u.Settings)` instead of the string-based version. – Yakimych Jun 25 '11 at 15:55
  • @Yaki - so your saying do SaveChanges twice? And yes - im using lambda include, this is just an example – RPM1984 Jun 26 '11 at 00:53
  • @RPM1984 - yes twice. And it doesn't seem to be such a bad idea. You will have two SQL commands executed anyways. – Yakimych Jun 26 '11 at 14:36
  • @Yakimych - yeah i guess. This was basically what i was doing to do as a last resort. So this behaviour im seeing is not standard? E.g i've done something wrong? – RPM1984 Jun 26 '11 at 23:33
  • @RPM1984 - I don't think you are doing anything wrong. Why do you expect the tables to be updated in the particular order you want? Any particular reason? – Yakimych Jun 28 '11 at 02:19
  • @Yakimych - well it's not really so much **what i want**, as it is **what it should be**. Parent tables should always be updated before child tables, since the child table's FK points to the parent's table's PK (e.g a child cannot exist without a parent). Why would the parent be done first with a INSERT, but done second with an UPDATE? doesnt make any sense. – RPM1984 Jun 28 '11 at 03:00
  • @RPM1984: Maybe it does - at least with the insert. You mentioned yourself that you can't insert a child without knowing the the parent Id. For an update, I don't see how this: `since the child table's FK points to the parent's table's PK` is a reason the update should happen from child to parent. Furthermore, in case of `Delete` (without triggers), it would be quite the opposite. It would not be possible to go from Parent to Child at all (since as you mentioned, a child cannot exist without a parent). So I am not sure about your reasoning on this one and whether that's the way `it should be`. – Yakimych Jun 28 '11 at 04:35
  • @Yakimych - if you want to DELETE a child, you can, that's fine. If you DELETE the parent, the cascading FK will delete the child. My point is, the order should be standard. When you INSERT, it's parent, then child. Why should it be flipped for an UPDATE? Anyway, over it - the workaround does the job, but i still think this is EF's fault. – RPM1984 Jun 28 '11 at 10:29
  • @RPM1984 - Deleting a parent is fine if you have cascading deletes set up, otherwise you will get problems unless you delete children before parents. Therefore it is safer to delete children and then parents. In any case, there is a clear reason for insert to be performed in a specific order, while there is none for an update (at least nothing obvious), so I wouldn't consider it a fault or bug. – Yakimych Jun 28 '11 at 11:46
  • If you are really interested in whether there is a reason for this order, you could try asking @Alex James. Sometimes there are some obscure innerworkings we don't have a clue about, such as in this question: http://stackoverflow.com/questions/5922207/ef-4-1-why-does-turning-a-constant-into-a-variable-result-in-extra-sub-query/5923157#5923157 – Yakimych Jun 28 '11 at 11:47
  • @Yakimych - there are plenty of EF innerworks i don't have a clue about. I've used EF heavily in this project, and i doubt i will be using it again. I'll probably try out NHibernate, and if that has the same problems as i've found in EF, then i'll be doing with classic ADO.NET with a thin wrapper, such as Massive/Dapper or a custom wrapper. Over EF. – RPM1984 Jun 28 '11 at 12:07

2 Answers2

1

Sorry, But I have tried your model in my PC. And All happened very well. User update first (Parent), then UserSetting (Child).

I think, It might be something wrong with your model setting or database setting, but I don't know what.

Agus Syahputra
  • 436
  • 4
  • 12
0

Ended up "touching" the field again as a workaround.

Damn you EF.

RPM1984
  • 72,246
  • 58
  • 225
  • 350