2013-03-19 2 views
5

В n-уровневом приложении linq-to-sql, похоже, не имеет четкого решения для обновления отключенного объекта с дочерними EntitySets.Обновление отключенной сущности с дочерними объектами в linq to sql

У меня есть некоторые LINQ-to-SQL объекты ...

public partial class Location : INotifyPropertyChanging, INotifyPropertyChanged 
{  
    public int id;  
    public System.Nullable<int> idLocation;  
    public string brandingName;  
    public System.Data.Linq.Binary timeStamp;  
    public EntitySet<LocationZipCode> LocationZipCodes; 
} 

public partial class LocationZipCode : INotifyPropertyChanging, INotifyPropertyChanged 
{ 
    public string zipcode;  
    public string state;   
    public int idLocationDetail;   
    public int id;  
    public System.Data.Linq.Binary timeStamp;  
    public EntityRef<Location> Location; 
} 

Так Location предприятие будет иметь EntitySet из LocationZipCodes.

Модель домена Location сопоставляется с моделью представления, которую слой представления потребляет, а затем в конечном итоге отправляет обратно измененный объект модели представления, где он сопоставляется с доменной моделью Location. Оттуда я обновляю объект и сохраняю изменения. Вот обработчик:

public class ProgramZipCodeManagerHandler : IHttpHandler { 
    private LocationsZipCodeUnitOfWork _locationsZipCodeUnitOfWork = new LocationsZipCodeUnitOfWork(); 

    public void ProcessRequest(HttpContext context) { 
     if (context.Request.HttpMethod == "POST") { 
      string json = Json.getFromInputStream(context.Request.InputStream); 

      if (!string.IsNullOrEmpty(json)) { 
       Location newLocation = Json.deserialize<Location>(json); 
       if (newLocation != null) { 
        //this maps the location view model from the client to the location domain model 
        var newDomainLocation = new Mapper<Location, DomainLocation>(new DomainLocationMapTemplate()).map(newLocation); 

        if (newDomainLocation.id == 0) 
         _locationsZipCodeUnitOfWork.locationRepository.insert(newDomainLocation); 
        else 
         _locationsZipCodeUnitOfWork.locationRepository.update(newDomainLocation); 

        _locationsZipCodeUnitOfWork.saveChanges(ConflictMode.ContinueOnConflict); 

        var viewModel = new Mapper<DomainLocation, Location>(new LocationMapTemplate()).map(newDomainLocation); 
        context.Response.ContentType = "application/json"; 
        context.Response.Write(Json.serialize(viewModel); 
       } 
      } 
     }  
    } 
} 

Здесь метод обновления в моем locationRepository:

protected System.Data.Linq.Table<T> _table; 

public void update(T entity) { 
    _table.Attach(entity, true); 
    _context.Refresh(RefreshMode.KeepCurrentValues, entity); 
} 

public void update(T newEntity, T oldEntity) { 
    _table.Attach(newEntity, oldEntity); 
    _context.Refresh(RefreshMode.KeepCurrentValues, newEntity); 
} 

Я могу видеть, что все записи, непосредственно связанные с Location сущности обновляется, но коллекция детской (public EntitySet<LocationZipCode> LocationZipCodes) является не обновляется.

Есть ли четкий способ обновления отключенного объекта, который имеет дочерний EntitySet, который также необходимо обновить? Другими словами, у меня есть отдельный объект, который имеет коллекцию другого объекта. Эта коллекция изменилась, и мне нужно обновить ее в базе данных.

+0

Имеются ли записи в детской коллекции с соответствующими идентификаторами? – rhughes

+0

Да, у них есть их id – bflemi3

ответ

2

Нет .. вы не можете этого сделать.

Прикрепление и отсоединение объектов за объект, с которым вы работаете, и не повлияет на связанные объекты (объекты).

Вы можете прочитать более подробную информацию здесь:
Attaching and Detaching Objects

Рассмотрим ситуацию, когда объект А связан с коллекции B, который заполнен 1000 значений. Вы отсоединяете A и отправляете его на некоторую удаленную обработку - A отправляется с нулевым значением в отношении B .. и теперь A возвращается в вашу программу - нет никакого способа узнать, что AB null является результатом удаленной обработки или это было дано удаленной обработке уже с нулем.

В ссылке, размещенной с этим ответом, пожалуйста, прокрутите вниз, чтобы прочитать внимательно в разделе под названием:
Соображения для отсоединения объектов.

+0

Я нашел этот вспомогательный класс, который выглядит как будет делать то, что я ищу http://linq2sqleb.codeplex.com/. Вы правы, но очень расстраиваетесь – bflemi3

0

Не совсем уверен, что я понимаю ваш вопрос, но здесь идет ... Что-то вроде следующего расширения объекта объекта, возможно, когда вы повторно привязываете объект к контексту и т. Д., Будет работать, повторно привязывая объект к контексту объекта и соответствующим образом определяя объект сущности.

/// <summary> 
    /// AttachEntityToObjectContext attaches an EntityObject to an ObjectContext 
    /// </summary> 
    /// <param name="entityWithRelationships">An EntityObject that has relationships</param> 
    /// <param name="newContext">The ObjectContext to attach the entity to</param> 
    /// <returns>True if the entity has relationships (and therefore the method could succeed). Otherwise false.</returns> 
    /// <remarks>Objects are retrieved using one ObjectContext, stored in ViewState and then 
    /// an attempt to save them is then made. The save attempt does not save the object. This is because it is a different context which is saving the object. 
    /// So the object needs to be detached from its old context, added to the new context and have its EntityState maintained so that it gets saved.</remarks> 
    public static bool AttachEntityToObjectContext(this IEntityWithRelationships entityWithRelationships, ObjectContext newContext) 
    { 
     EntityObject entity = entityWithRelationships as EntityObject; 
     if (entity == null) 
     { 
      return false; 
     } 

     if (entity.EntityState != EntityState.Detached) 
     { 
      ObjectContext oldContext = entity.GetContext(); 
      if (oldContext == null) 
      { 
       return false; 
      } 

      if (oldContext != newContext) 
      { 
       EntityState oldEntityState = entity.EntityState; 
       oldContext.Detach(entity); 
       newContext.Attach(entity); 
       newContext.ObjectStateManager.ChangeObjectState(entity, oldEntityState); 
      } 
     } 

     return true; 
    } 

    /// <summary> 
    /// GetContext gets the ObjectContext currently associated with an entity 
    /// </summary> 
    /// <param name="entity">An EntityObject</param> 
    /// <returns>The ObjectContext which the entity is currently attached to</returns> 
    private static ObjectContext GetContext(this IEntityWithRelationships entity) 
    { 
     if (entity == null) 
     { 
      throw new ArgumentNullException("entity"); 
     } 

     var relationshipManager = entity.RelationshipManager; 

     var relatedEnd = relationshipManager.GetAllRelatedEnds().FirstOrDefault(); 

     if (relatedEnd == null) 
     { 
      // No relationships found 
      return null; 
     } 

     var query = relatedEnd.CreateSourceQuery() as ObjectQuery; 

     if (query == null) 
     { 
      // The Entity is Detached 
      return null; 
     } 

     return query.Context; 
    } 
+0

Я обновил свой вопрос, надеюсь, лучше отразить мою проблему. – bflemi3

+0

Контексты linq-to-sql не имеют метода отсоединения. Это для EF? – bflemi3

+0

Да, это L2E, хотя я и сказал «что-то», надеясь указать вам в правильном направлении. Мы используем этот код для повторной привязки объектов, которые хранятся в кеше в представлении, в текущем контексте. –

Смежные вопросы