0

I have started working out with Entity Framework (EF) for an MVC n-tier application. It would seem that very obvious that this being a web application (which is stateless), I would have to use detached object models. There is no ambiguity with doing an Add operation. However when doing an edit there are here are two ways

  1. Fetch the original object in context, attach the updated object and then save to database. Something like mentioned in answer to this question EF4 Context.ApplyCurrentValues does not update current values
  2. Set individual modified properties explicitly using the IsModified property of individual fields of the object like mentioned in this article http://msdn.microsoft.com/en-us/data/jj592677.aspx

Method 1 has disadvantage of having to load object into memory from database each time an update needs to be performed. Method 2 would require having to manually pass which fields to be set as IsModified to true from wherever the object an be updated. So for e.g. for each object, I may need to create a boolean collection object for each field of the object. e.g.

SaveEntity(EntityClass e, EntityStateClass ec)
{
  context.Entry(e).Property("Name").IsModified = ec.NameState;

  context.SaveChanges();
}

class EntityStateClass{ public bool NameState;} 

I would prefer method 2 simply for the sake of performance but I am hindered by the n-tier architecture and repository pattern I am using. My Repository interface restricts save method for any object to be

 SaveEntity(EntityClass e);

So I cannot pass the "state" object. Context class is not available and should not be available outside DAL. So I cannot set property outside. Is there any "proper" way to achieve this ?
Note: Self-Tracking Entity is also out of question since I cannot send entities with state to client (the browser) since I am intent on keeping the html lightweight.

EDIT: After a lot of thinking, I am trying to use following mechanism to keep track of modified state for each field in my domain class

  • Declare a partial class for entity class.
  • For each field that is updateable, declare a boolean property like "IsModified_FieldName"
  • Set the "IsModified_FieldName" property when the field is set.

However for this I need Entity Framework to generate explicit properties for me instead of implicit properties that it auto-generates. Does EF provide an handle to do this ?

Here is sample code of what I am trying to achieve

 //Save Method for class EntityClass. 
 SaveEntity(EntityClass e)
 {
   context.Entry(e).Property("Name").IsModified = e.IsModified_Name;
   context.SaveChanges();
 }

//EntityClass is class autogenerated by EF
 public partial class EntityClass
  {

        //This is auto-generated property by EF
        public string Name {get; set;}

        /* This is what I would like EF to do
            private string name;
            public string Name 
            {
               get {return Name;}
               set {
                     name = value;
                     //this is what I would like to do
                     this.IsModified_Name = true;
                   };

            }
         */
 }

 //This is another partial definition for EntityClass that I will provide
  public partial class EntityClass
  {
     //This property will be set to true if "Name" is set
      public bool IsModified_Name {get; set;}
  }

PS: It seems the information I have provided is not sufficient and therefore there are no responses.

  • I am using DbContext (Database first model)
  • EF auto-generates the class files for me. So each time I update my database, the class files are regenerated.
Community
  • 1
  • 1
devanalyst
  • 1,348
  • 4
  • 28
  • 55

1 Answers1

1

To your concrete question: The entities are generated by a T4 template and it should be possible to modify this template (which is in text format) to generate the entities in a way you want to shape them.

But I have a few remarks about your concept:

  • In a web application data are usually changed by a user in a browser. To have a definite knowledge what really has been changed you need to track the changes in the browser (probably by some Javascript that sets flags in the data (a ViewModel for example) when a user edits a text box for instance).

    If you don't track the changes in the browser what happens? The data get posted back to the server and you don't know at the server side (with MVC in a controller) which property has been changed. So, your only chance is to map all properties that has been posted back to your EntityClass and every property will be marked as Modified, no matter if the user really did a change or not. When you later call SaveChanges EF will write an UPDATE statement that involves all those properties and you have an unnecessary overhead that you you want to avoid.

  • So, what did you win by setting individual properties instead of setting the whole entity's state to Modified? In both cases you have marked all properties as Modified. Exceptions are partial changes of an entity, for example: You have a Customer entity that has a Name and City property and a view that only allows to edit the Name but not the City and a corresponding ViewModel that only contains a Name property. In this case your procedure would only mark the Name property of the Customer entity as Modified but not the City. You might save here a little bit because you don't save the City property value to the database. But you still save the Name even if it didn't change.

  • If you use solution 1 (ApplyCurrentValues) you have to load the entity first from the database, yes, but it would only mark the properties as Modified that really changed compared to their values in the database. If the user didn't change anything no UPDATE would be written at all.

  • Keep in mind that you are only at the beginning to implement your concept. There are other changes to the data that can happen in the browser than only scalar property changes, namely relationship changes. For example a user changes the relationship from an Order to a Customer or you have a view that has an Order and a collection of OrderItems and the user cannot only edit the Order header but also edit the OrderItems and remove and add new OrderItems. How do you want to recognize when the data come back from the browser to the server which collection item has been added and which has been removed - unless you track all those changes in the browser and send tracking information back to the server in addition to the actual data or unless you reload the Order and OrderItems from the database and merge the changes into the original entities from the database?

Personally I would vote for option 1 for these reasons:

  • You can use real POCOs that don't carry additional tracking information. (BTW: I have some doubt if you aren't reinventing the wheel by implementing your own tracking that EF change tracking proxies provide out of the box.)

  • You don't need to track changes in the browser which can become quite complex and will require Javascript in every Edit view to write change flags into hidden form fields or something.

  • You can use standard features of EF without having to implement your own tracking.

  • You are required to load entities from the database when you want to update an entity, that's true. But is this the real performance bottleneck in a web application where data have to run through the wire back and forth (and reflection (which isn't really known as to be fast) is involved by the model binder)? I have nothing said if your database is remote from the web server and connected by a 9600 baud modem. But otherwise, your plan is not only premature optimization, it is kind of premature architecture. You are starting to build a potentially complex architecture based on "it could be slow" to solve a performance problem that you actually don't know of whether it really exists.

Community
  • 1
  • 1
Slauma
  • 175,098
  • 59
  • 401
  • 420