2013-03-19 10 views
5

W aplikacji n-warstwowej linq-sql nie wydaje się mieć jednoznacznego rozwiązania do aktualizacji odłączonego obiektu, który ma podrzędne jednostki EntitySets.Aktualizowanie odłączonego elementu zawierającego elementy podrzędne w linq do sql

Mam LINQ-SQL podmioty ...

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; 
} 

Więc podmiot Location miałoby EntitySet z LocationZipCodes.

Model domeny modelu Location zostaje zmapowany do modelu widoku, który warstwa prezentacji pochłania, a następnie ostatecznie odsyła zmieniony model widoku widoku, w którym jest mapowany z powrotem do modelu domeny Location. Stamtąd aktualizuję encję i zapisuję zmiany. Oto obsługi:

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); 
       } 
      } 
     }  
    } 
} 

Oto sposób zmiana w moim 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); 
} 

widzę, że wszystkie zapisy związane bezpośrednio z jednostką Location są zaktualizowane, ale kolekcji dziecięcej (public EntitySet<LocationZipCode> LocationZipCodes) jest nie aktualizowane.

Czy istnieje wyraźny sposób aktualizowania odłączonego obiektu, który ma podrzędny zestaw jednostek EntitySet, który również wymaga aktualizacji? Innymi słowy, mam odłączony podmiot, który ma kolekcję innego podmiotu. Ta kolekcja uległa zmianie i muszę ją zaktualizować w bazie danych.

+0

Czy wpisy w kolekcji dziecka mają odpowiednie identyfikatory? – rhughes

+0

Tak, mają swój identyfikator – bflemi3

Odpowiedz

2

Nie. Nie możesz tego zrobić.

Dołączanie i odłączanie obiektów odbywa się za obiekt, z którym pracujesz i nie wpływa na powiązane obiekty (encje).

Możesz przeczytać więcej informacji tutaj:
Attaching and Detaching Objects

Rozważmy sytuację, w której obiekt A jest związany z kolekcji B, która jest wypełniona 1000 wartości. Odłączasz A i wysyłasz go do jakiegoś zdalnego przetwarzania - A jest wysyłane z null w relacji B .. a teraz A jest zwracane do twojego programu - nie ma sposobu, aby wiedzieć, że AB null jest wynikiem zdalnego przetwarzania lub został przekazany do zdalnego przetwarzania już z wartością null.

W linku wysłanym z tą odpowiedzią - przewiń w dół, aby uważnie przeczytać w sekcji zatytułowanej:
Uwagi dotyczące odłączania obiektów.

+0

Znalazłem tę klasę pomocnika, która wygląda tak, jak zrobię to, czego szukam http://linq2sqleb.codeplex.com/. Masz jednak rację, bardzo frustrujące – bflemi3

0

Nie jestem pewien, czy rozumiem twoje pytanie, ale tutaj idzie ... Coś takiego jak rozszerzenie obiektu obiektu, być może tam, gdzie ponownie podłączysz obiekt do kontekstu itp., Będzie działało przez ponowne podłączenie obiektu do kontekstu obiektu i odpowiednie ustawienie entitystate.

/// <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

Zaktualizowałem moje pytanie, aby, mam nadzieję, lepiej odzwierciedlić mój problem. – bflemi3

+0

konteksty linq-sql nie mają metody odłączania. Czy to dla EF? – bflemi3

+0

Tak, to L2E, chociaż powiedziałem "coś" w ten sposób, mając nadzieję wskazać ci właściwy kierunek. Używamy tego kodu do ponownego dołączania jednostek, które są przechowywane w pamięci podręcznej w widoku, do bieżącego kontekstu. –

Powiązane problemy