2013-03-19 81 views
5

在n層應用程序中,linq-to-sql似乎沒有明確的解決方案來更新具有子EntitySets的斷開連接的實體。更新在linq中有子實體的斷開連接的實體到sql

我有一些LINQ到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實體將有LocationZipCodesEntitySet

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)相關的所有記錄是沒有被更新。

是否有一個明確的方法來更新一個斷開的實體,該實體的子實體集也需要更新?換句話說,我有一個擁有另一個實體集合的分離實體。該集合已更改,我需要在數據庫中更新它。

+0

子集合中的條目是否有其各自的ID? – rhughes 2013-03-22 12:40:46

+0

是的,他們有他們的編號 – bflemi3 2013-03-22 12:48:04

回答

2

不,你不能那樣做。

附加和分離對象是您使用的每個對象,不會影響相關對象(實體)。

從這裏你可以讀出更多的信息:
Attaching and Detaching Objects

考慮這樣一個對象是與這充滿1000個值的集合B中的情況。 您分離A並將其發送給某個遠程處理 - A在B關係中以null發送..現在A被帶回到您的程序 - 無法知道AB null是遠程處理的結果還是它是否已經以空值被賦予遠程處理。

在此答案發布的鏈接中,請向下滾動閱讀標題爲:
注意對象的注意事項。

+0

我發現這個助手類似乎會做我正在尋找http://linq2sqleb.codeplex.com/。你是對的,但是非常令人沮喪 – bflemi3 2013-03-28 17:26:23

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 2013-03-26 14:25:44

+0

linq-to-sql上下文沒有分離方法。這是EF嗎? – bflemi3 2013-03-27 16:25:49

+0

是的,它是L2E,雖然我確實說過這樣的「某種東西」,希望能指出你正確的方向。我們使用此代碼重新存儲視圖中緩存中存儲的實體到當前上下文。 – 2013-03-28 08:50:15