EF4 / WCF SaveChanges最佳实践

问题描述

| 这就是我们在WCF中为我们的EF实体实现通用Save()服务的方式。 TT为我们完成了工作。即使我们没有任何问题,我也不愿假定这是最好的方法(即使可能)。你们似乎很聪明,乐于助人,所以我想提出一个问题: 有没有更好的办法?
[OperationContract]
public User SaveUser(User entity)
{
    bool _IsDeleted = false;
    using (DatabaseEntities _Context = new DatabaseEntities())
    {
        switch (entity.ChangeTracker.State)
        {
            case ObjectState.Deleted:
                //delete
                _IsDeleted = true;
                _Context.Users.Attach(entity);
                _Context.DeleteObject(entity);
                break;
            default:
                //everything else
                _Context.Users.ApplyChanges(entity);
                break;
        }
        // Now,to the database
        try
        {
            // try to save changes,which may cause a conflict.
            _Context.SaveChanges(System.Data.Objects.SaveOptions.None);
        }
        catch (System.Data.OptimisticConcurrencyException)
        {
            // resolve the concurrency conflict by refreshing 
            _Context.Refresh(System.Data.Objects.RefreshMode.ClientWins,entity);
            // Save changes.
            _Context.SaveChanges();
        }
    }
    // return
    if (_IsDeleted)
        return null;
    entity.AcceptChanges();
    return entity;
}
    

解决方法

        您为什么要使用自我跟踪实体?这有什么问题:
[OperationContract]
public User SaveUser(User entity)
{
    bool isDeleted = false;
    using (DatabaseEntities context = new DatabaseEntities())
    {
        isDeleted = entity.ChangeTracker.State == ObjectState.Deleted;
        context.Users.ApplyChanges(entity); // It deletes entities marked for deletion as well

        try
        {
            // no need to postpone accepting changes,they will not be accepted if exception happens
            context.SaveChanges(); 
        }
        catch (System.Data.OptimisticConcurrencyException)
        {
            context.Refresh(System.Data.Objects.RefreshMode.ClientWins,entity);
            context.SaveChanges();
        }
    }

    return isDeleted ? null : entity;
}
    ,        如果我没有记错的话,人们通常不会直接在WCF服务中公开其Entity Framework对象。通常将实体框架视为数据访问层,而WCF更像是前端层,因此将它们放在不同的层上。 WCF方法中使用了数据传输对象(DTO)。通常,这是一个POCO,它没有任何状态跟踪。然后将DTO手动或通过诸如AutoMapper的框架映射到实体。 通常,客户应该知道它们是“添加”还是“更新”对象,而我个人更希望它们是服务接口上的两个独立操作。另外,我绝对会要求他们使用单独的方法删除对象。但是,如果您绝对需要通用的“保存”,则应该基于主键值的存在(或不存在)来判断给出的对象是否为“新”。 。 许多代码可以放入通用实用程序中。例如,假设您的T4模板在实体的键值上产生属性,则可以自动确定键值是否存在并相应地执行插入/更新。同样,您正在使用的“ 2”块(虽然可能不是必需的)可以轻松地放入简单的实用程序方法中,使其更加干燥。