2

We've been using EF STEs for a while, but our application has grown quite a bit and we decided to sue the new 4.1 DbContext so we can "evolve" a separate business layer on top of our data layer without having to use different types for it.

In the elementary evaluation for the DbContext way of doing things, I am facing a little problem.

I am used to query and preload required related data like:

return context.Orders.Include("Detail").SingleOrDefault(ord => ord.ID == ID);

And then send the returned object to the UI for modification, and when returned from the UI save the changes to the database.

From what I read so far, doing the "change saving" in DbContext is easily done using code like this:

context.Entry(order).State = EntityState.Modified;

The problem with this code is that it actually marks all properties in the object as modified, a thing that's not allowed for some properties in my model (a business rule).

I resorted to the following solution (which seems to require a lot of code for a relatively small requirement! BTW, changing a modified property state to Unchanged is not supported):

context.Orders.Attach(order);

DbEntityEntry<Order> ordEntity = context.Entry(order);

string[] arr =
{
      ordEntity.Property(ord => ord.ID).Name,
      ordEntity.Property(ord => ord.ClientID).Name,
};

foreach (string prop in ordEntity.OriginalValues.PropertyNames)
{
      if (!arr.Contains(prop))
      {
            ordEntity.Property(prop).IsModified = true;
      }
}

context.SaveChanges();

The problem I am facing with this code is that the "Attach" statement is throwing an exception saying that there is some sort of conflict in the navigation properties in the attached object, even if no changes were made to anything at all! (saving the object exactly as it was retrieved from the database). The error message is something like: "Conflicting changes to the role 'Detail' of the relationship 'OrdersDatamodel.FK_Order_Detail' have been detected."

The questions are:

  1. Is there a more "elegant" way for preventing the modification of certain object properties?
  2. Does anybody know what's going on with the exception raised when attaching the object to the context?

Thanks.

wassim
  • 69
  • 1
  • 12

1 Answers1

2

From what I read so far, doing the "change saving" in DbContext is easily done using code like this:

context.Entry(order).State = EntityState.Modified;

You rarely need to explicitly set the state. When you modify properties, assuming they are virtual, the state will automatically change to Modified without you having to set it. Otherwise, DetectChanges will pick this up during your call to SaveChanges.

  • I am not using this code anymore. Like I mentioned in my question, I had to manually attach the object to the context (which leaves the object in the "Unchanged" state) then mark the properties that are allowed to change manually. Thanks anyway. – wassim Feb 18 '12 at 14:03
  • But the point I'm trying to make is that you're trying to solve a non-problem. You don't have to manually mark the entity/properties as modified, because EF does it for you. –  Feb 18 '12 at 14:06
  • My problem with the out-of-the-box behavior you are talking about, is that it allows the modification of any property. I cannot allow the modification of certain properties so I need to make sure only a specified set of properties get flagged as modified (whether the flagging happens automatically or manually is not really the problem. I chose to flag them as modified manually because my efforts to "un-flag" the read-only properties have failed!). – wassim Feb 19 '12 at 13:05
  • Ah, thanks for the clarification. Is it an option to prevent modifications to those properties in the first place (by having the property setter throw an exception, depending on the object state), instead of trying to revert the changes afterwards? Or are internal nonpersisted modifications intended? –  Feb 19 '12 at 19:14