【问题标题】:Updating disconnected entity that has child entities in linq to sql将 linq 中具有子实体的断开连接的实体更新为 sql
【发布时间】:2013-03-19 15:35:47
【问题描述】:

在 n 层应用程序中,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 实体将具有 EntitySetLocationZipCodes

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&lt;LocationZipCode&gt; LocationZipCodes) 没有更新。

是否有一种明确的方法来更新具有子 EntitySet 的断开连接的实体也需要更新? 换句话说,我有一个分离的实体,它具有另一个实体的集合。该集合已更改,我需要在数据库中对其进行更新。

【问题讨论】:

  • 子集合中的条目有各自的id吗?
  • 是的,他们有自己的身份证

标签: c# linq-to-sql


【解决方案1】:

不……你不能那样做。

附加和分离对象取决于您使用的对象,不会影响相关对象(实体)。

您可以从这里阅读更多信息:
Attaching and Detaching Objects

考虑一种情况,其中对象 A 与一个集合 B 相关,该集合 B 填充了 1000 个值。 您分离 A 并将其发送到某个远程处理 - A 在 B 关系中以 null 发送.. 现在 A 被带回您的程序 - 无法知道 A.B null 是远程处理的结果还是它已经以 null 提供给远程处理。

在与此答案一起发布的链接中 - 请向下滚动以仔细阅读标题为:
分离对象的注意事项。

【讨论】:

  • 我发现这个帮助类看起来可以满足我的需求linq2sqleb.codeplex.com。不过你是对的,非常令人沮丧
【解决方案2】:

我不太确定我是否理解您的问题,但这里有......类似以下实体对象扩展的内容可能会在您将实体重新附加到上下文等的地方通过将实体重新附加到对象上下文并适当地设置实体状态来工作。

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

【讨论】:

  • 我已经更新了我的问题,希望能更好地反映我的问题。
  • linq-to-sql 上下文没有分离方法。这是 EF 的吗?
  • 是的,它是 L2E,虽然我确实说过类似这样的“某事”,但希望能为您指明正确的方向。我们使用此代码将存储在视图缓存中的实体重新附加到当前上下文。
猜你喜欢
  • 2015-11-02
  • 2018-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 2012-03-13
  • 1970-01-01
相关资源
最近更新 更多