2
\$\begingroup\$

I have a WCF service, which has a method for updating a EF entity. The update method works just fine but looks ugly. I think due to some EF design I have to manually set the change tracker state to Modified or Deleted or Added. The update method in the server side looks like this:

public Event UpdateEvent(Guid sessionID, Event _event)
{
 Session session = IFSHelperClass.CheckSession(sessionID);
 try
 {
 using (IFSDB ifsdb = new IFSDB())
 {
 ifsdb.Events.Attach(_event);
 ifsdb.ObjectStateManager.ChangeObjectState(_event, System.Data.EntityState.Modified);
 // mark the modified and added items
 // for the navigation property 'EventPersons'
 foreach (var p in _event.EventPersons)
 {
 if (p.ChangeTracker.State == IFSEntities.ObjectState.Added)
 ifsdb.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Added);
 if (p.ChangeTracker.State == IFSEntities.ObjectState.Modified)
 ifsdb.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Modified);
 }
 // since the deleted items will not be available in the
 // navigation property, delete them manually from the
 // ChangeTracker object.
 if (_event.ChangeTracker.ObjectsRemovedFromCollectionProperties.Count > 0)
 {
 var personsToDelete = _event.ChangeTracker.ObjectsRemovedFromCollectionProperties.Where(t => t.Key == "EventPersons").Select(t => t.Value)
 .FirstOrDefault()
 .ToList();
 foreach (EventPerson p in personsToDelete)
 {
 ifsdb.EventPersons.Attach(p);
 ifsdb.EventPersons.DeleteObject(p);
 }
 }
 // save all changes and accept them
 ifsdb.SaveChanges();
 _event.AcceptChanges();
 foreach (var p in _event.EventPersons)
 p.AcceptChanges();
 return _event;
 }
 }
 catch (Exception ex)
 {
 Logger.LogError("UpdateEvent()", ex.Message, ex.ToString(), session.User.UserID);
 throw ex;
 }
 }

As you can see, II iterate through the navigation property items to check for updates or deletes and mark them manually.

Is this the way? or am I doing something ugly here?

asked Jun 1, 2013 at 14:14
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

You shouldn't expose entities in WCF service. Every change in entity will cause WCF webservice change and incompatibility for existing consumers. I would create decicated data transfer objects for WCF webservice and use library like Automapper to handle property mapping.

EF entities often contain various properties (example: creation date, creator info), that shouldn't be modified, but when you expose whole entities, you allow this, which in future may cause security issues.

Small example (without Automapper):

public class EventDTO 
{
 public int Id { get; set; }
 public DateTime EventDate { get; set; }
 public string Title { get; set; }
}

In webservice class:

public Event UpdateEvent(Guid sessionID, EventDTO eventDTO)
{
 using (IFSDB ifsdb = new IFSDB())
 {
 var event = ifsdb.Events.First(item => item.Id == eventDTO.Id);
 event.EventDate = eventDTO.EventDate;
 event.Title = eventDTO.Title;
 ifsdb.SaveChanges();
 }
}
answered Jun 1, 2013 at 21:01
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.