Posts
208
Comments
1144
Trackbacks
51
Attaching Modified Entities in EF 4

Lately I’ve been working with EF 4.0 and finding that many of the new features are catching up with the features previously available in other framework like LINQ to SQL.  One example of this is the ability to easily attach objects (for example, disconnected objects that come in from another tier).  For example, imagine you had a web service where a consumer submitted an object to get saved – you’d want to instantiate a new context, attach the incoming entity, and save the object.  In previous versions of EF, this was not a trivial thing to do.  However, this was always quite easy to do in LINQ to SQL by doing this:

   1:  using (var dataContext = new MyDataContext())
   2:  {
   3:      dataContext.Contacts.Attach(someEntity, true);
   4:      dataContext.SubmitChanges();
   5:  }

Notice the second Boolean parameters of the Attach() method – this instructs the context that the entity should treated “as modified” so that an UPDATE command should be issued for that entity when SubmitChanges() gets called (LINQ to SQL also provides an AttachAll() method for collections).  You can now do the same thing in EF 4 like this (I’m using POCO and Code Only here):

   1:  using (var dataContext = new MyDataContext())
   2:  {
   3:      dataContext.Contacts.Attach(contact);
   4:      dataContext.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
   5:      dataContext.SaveChanges();
   6:  }

This is a huge leap forward from previous versions of EF but notice that this actually takes one more line of code than its LINQ to SQL counterpart because an explicit call to the ObjectManager’s ChangeObjectState() method must be called. Although this might appear to be a slight inconvenience, it is possible to write a couple of extension methods to simplify this since the ObjectSet’s all have a reference to the parent Context:

   1:  static class ContextExtensions
   2:  {
   3:      public static void AttachAsModified<T>(this ObjectSet<T> objectSet, T entity) where T : class
   4:      {
   5:          objectSet.Attach(entity);
   6:          objectSet.Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
   7:      }
   8:   
   9:      public static void AttachAllAsModified<T>(this ObjectSet<T> objectSet, IEnumerable<T> entities) where T : class
  10:      {
  11:          foreach (var item in entities)
  12:          {
  13:              objectSet.Attach(item);
  14:              objectSet.Context.ObjectStateManager.ChangeObjectState(item, EntityState.Modified);
  15:          }
  16:      }
  17:  }

This allows you to now save like this:

   1:  using (var dataContext = new MyDataContext())
   2:  {
   3:      dataContext.Contacts.AttachAsModified(contact);
   4:      dataContext.SaveChanges();
   5:  }

This is pretty straight forward and certainly not very complex. However, it is promising that EF is moving in the direction of better enabling these simple scenarios as compared with previous versions.

posted on Friday, November 27, 2009 10:12 PM Print
Comments
Gravatar
# re: Attaching Modified Entities in EF 4
Sean
1/7/2010 10:00 PM
What happens when you Attach() an entity that is already associated with another context?
Gravatar
# re: Attaching Modified Entities in EF 4
Steve
1/7/2010 10:04 PM
@Sean - That depends. If you're using EF in the POCO model, the entity won't even have any knowledge about another context because it won't have any reference to its parent context. If it's a "traditional" EF model, then my assumption is that it would act similar to LINQ to SQL and not allow it but I have yet to test that scenario so I can't answer it with any authority.
Gravatar
# re: Attaching Modified Entities in EF 4
Sean Fao
1/8/2010 9:16 AM
@Steve

Very cool. Are you building your POCO entities and context by hand? I read on the ADO.NET team blog that Microsoft was planning on including T4 templates for this purpose, but I don't think this made it into Visual Studio 2010 (at least not that I have seen). I have, however, come across some POCO templates a few days ago, which I've been meaning to try. Are you aware of anything else that is more official?

Thank you again,

Sean
Gravatar
# re: Attaching Modified Entities in EF 4
Sean Fao
1/8/2010 9:16 AM
By the way, when I say that the templates didn't make it into Visual Studio 2010, I should have mentioned that I'm currently working with beta 2.
Gravatar
# re: Attaching Modified Entities in EF 4
Steve
1/8/2010 9:19 AM
The POCO templates were not included in the latest release (though they were included in a previous release). In the above example, I'm using "code only" - which means I'm not relying on any auto-generated code from templates - I'm controlling all code myself by hand.
Gravatar
# re: Attaching Modified Entities in EF 4
Sean Fao
1/9/2010 2:43 PM
Cool. I have a project coming up in which the tables have over 100 columns (the client has control of the database so there really isn't anything I can do to simplify the model). I was hoping there was an easier way of generating POCO entities that I simply wasn't aware of.

By the way, it appears the T4 templates I found were for an earlier release of EF. If I get them working, I'll share them in a blog post.

Thank you for your help,

Sean
Gravatar
# re: Attaching Modified Entities in EF 4
leo
11/11/2011 2:32 AM
What happened when call Attach Method
Gravatar
# re: Attaching Modified Entities in EF 3.5
Ravi
1/23/2012 5:37 AM
Hi,

How to change the state of the Entity from Modified to Added in Entity frame work 3.5. Not using EF 4.

Here is my code

ObjectStateEntry objEn;
DbEntity.ObjectStateManager.TryGetObjectStateEntry(delrHistory, out objEn);

if (objEn.State == System.Data.EntityState.Modified)
{
//objEn.State = System.Data.EntityState.Added;

//I'm not able to uncomment as it saying read only property. But I need the Entity state should be added to add a new item.

DbEntity.Detach(delrHistory);
DbEntity.CreateEntityKey("AGMT_DELR_HISTS", delrHistory);
DbEntity.Attach(delrHistory);
DbEntity.SaveChanges();


}

Please do needful.

Thanks
Ravi
Gravatar
# re: Attaching Modified Entities in EF 4
Ravi
1/24/2012 1:31 AM
Hi

How to change the state of the Entity from Modified/Unchanged to Added entity state in Entity frame work 3.5. Not using EF 4.

Here is my code


public string UpdateAllAgreementDealers(REFIEntities context, long agmtId, DateTime expirationDate, string userId)
{
IQueryable<AGMT_DELR> agmtDelr;
REFI.DAL.EntityFW.AGMT_DELR agmtDlr;
REFI.DAL.EntityFW.AGMT_DELR_HIST delrHistory = new AGMT_DELR_HIST();
string delrHistoryValue = "TRUE";
System.Data.EntityKey ent;
try
{
agmtDelr = (from item in context.AGMT_DELRS
where item.AGMT.AGMT_ID_REFI == agmtId
select item);

foreach (var item in agmtDelr)
{
if (item.DELR_CONTR_EXPI_DT > expirationDate)
{
agmtDlr = GetAgmtDealer(item.AGMT_DELR_ID);
if (agmtDlr != null)
{
delrHistory.DELR_ID = agmtDlr.DELR.DELR_ID;
delrHistory.AGMT_DELR_ID = agmtDlr.AGMT_DELR_ID;
delrHistory.CONTR_TYP = agmtDlr.CONTR_TYP;
delrHistory.DELR_CONTR_EFF_DT = agmtDlr.DELR_CONTR_EFF_DT;
delrHistory.DELR_CONTR_EXPI_DT = agmtDlr.DELR_CONTR_EXPI_DT;
delrHistory.IS_CUR = agmtDlr.IS_CUR;
delrHistory.AGMT = agmtDlr.AGMT;
delrHistory.MOD_BY = userId;
delrHistory.MOD_DT = System.DateTime.Now;
delrHistory.CRTE_BY = userId;
delrHistory.CRTE_DT = System.DateTime.Now;
ObjectStateEntry objEn;
DbEntity.ObjectStateManager.TryGetObjectStateEntry(delrHistory, out objEn);
if (objEn.State == System.Data.EntityState.Modified)
{
//objEn.State = System.Data.EntityState.Added;
//I'm not able to uncomment the above line as it saying read only property. But I need the Entity state should be added to add a new item.


DbEntity.Detach(delrHistory);
DbEntity.CreateEntityKey("AGMT_DELR_HISTS", delrHistory);
DbEntity.Attach(delrHistory);
DbEntity.SaveChanges();

}

DbEntity.AddToAGMT_DELR_HISTS(delrhistory);
DbEntity.SaveChanges();
}
item.DELR_CONTR_EXPI_DT = expirationDate;
item.IS_CUR = true;
item.MOD_BY = userId;
item.MOD_DT = System.DateTime.Now;

}
}


if (agmtDelr != null)
return UpdateDealers();
else
return null;
}
catch (Exception e)
{
return null;
}
finally
{
agmtDelr = null;
}
}
Gravatar
# re: Attaching Modified Entities in EF 4
123
6/28/2015 12:52 PM
testing from matt
Gravatar
# re: Attaching Modified Entities in EF 4
123
6/28/2015 12:55 PM
Great blog post. Keep it up!

Post Comment

Title *
Name *
Email
Comment *  
Verification

View Steve Michelotti's profile on LinkedIn

profile for Steve Michelotti at Stack Overflow, Q&A for professional and enthusiast programmers




Google My Blog

Tag Cloud