首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EF6,工作单元和存储库模式--这是不是同步服务的错误模式?

EF6,工作单元和存储库模式--这是不是同步服务的错误模式?
EN

Stack Overflow用户
提问于 2015-03-12 21:44:39
回答 1查看 1.1K关注 0票数 0

我正在编写Salesforce环境和本地环境之间的同步服务。由于每天对# of API请求的限制,我使用Salesforce API纯粹是在批处理级别上,尽管我确实有原子级故障的详细信息。但是,我希望在本地环境中保存原子级的更改,因为如果一个实体失败,我不希望整个事务失败。

我正在使用实体框架6和一个工作单元和仓库模式。下面是我的相关代码(实现细节如下):

IUnitOfWork

代码语言:javascript
复制
public interface IUnitOfWork: IDisposable
{
    IReadUpdateRepository<EntityType1> EntityType1Repository { get; }
    ISyncRepository<EntityType2> EntityType2Repository { get; }
    ISyncRepository<EntityType3> EntityType3Repository { get; }
...other repos
    void SaveChanges();
}

IUnitOfWork的实现

代码语言:javascript
复制
public class UnitOfWork : IUnitOfWork
{
    private bool _isDisposed;
    private DbContext _context;
    private ISyncRepository<Entity> _entityRepo;

...other private repos
    public UnitOfWork(DbContext context)
    {
        _context = context;
    }


    public ISyncRepository<Entity> EntityRepository
    {
        get
        {
            if (_entityRepo == null)
                _entityRepo = new GenericSyncRepository<Entity>(_context);

            return _entityRepo ;
        }
    }

...other getters for other repos

    public void SaveChanges()
    {
        //client classes handle all errors here
        _context.SaveChanges();
    }

    private void dispose(bool isDisposing)
    {
        if (!_isDisposed)
        {
            if (isDisposing)
                _context.Dispose();
        }

        _isDisposed = true;
    }

    public void Dispose()
    {
        dispose(true);
    }
}

ISyncRepository

代码语言:javascript
复制
public interface ISyncRepository<T> where T : BaseEntity
{
    void DeleteItems(IEnumerable<T> items);
    void DeleteItemsById(IEnumerable<int> ids);
    void DeleteItem(T item);
    void InsertItems(IEnumerable<T> items);
    void Insert(T item);
    T GetItemById(int id);
    List<T> GetItems(Expression<Func<T, bool>> predicate = null,     Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "");

}

ISyncRepository的实现

代码语言:javascript
复制
public class GenericSyncRepository<T> : ISyncRepository<T> where T : BaseEntity
{
    private readonly DbContext _context;
    private readonly DbSet<T> _set;

    public GenericSyncRepository(DbContext context)
    {
        _context = context;
        _set = _context.Set<T>();
    }

    public T GetItemById(int id)
    {
        var result = _set.Find(id);

        return result;
    }

    public List<T> GetItems(Expression<Func<T, bool>> predicate = null, Func<IQueryable<T>,IOrderedQueryable<T>>  orderBy = null ,string includeProperties = "")
    {
        IQueryable<T> query = _set.AsExpandable();

        if (predicate != null)
        {
            query = query.Where(predicate);
        }


        if (!String.IsNullOrEmpty(includeProperties))
        {
            var splitProps = includeProperties.Split(',');
            foreach (var prop in splitProps)
            {
                query = query.Include(prop);
            }
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }

        return query.ToList();
    }

    public void DeleteItemsById(IEnumerable<int> ids)
    {

        var items = ids.Select(i => _set.Find(i));

        DeleteItems(items);
    }

    public void DeleteItem(T item)
    {
        _set.Remove(item);
    }

    public void DeleteItems(IEnumerable<T> items)
    {
        _context.Set<T>().RemoveRange(items);
    }

    public void Insert(T item)
    {
        _set.Add(item);
    }

    public void InsertItems(IEnumerable<T> items)
    {
        _set.AddRange(items);
    }

    public List<T> GetViewItems(Expression<Func<T, bool>> predicate)
    {
        IQueryable<T> query = _set.AsExpandable();

        return query.Where(predicate).ToList();
    }
}

我在与同步中涉及的每个对象组相关的服务中使用这个存储库,我通过构造函数将IUnitOfWork注入其中:

代码语言:javascript
复制
 private readonly IUnitOfWork _uow;

public EntityDataService(IUnitOfWork uow, ICamsSfDTOMapper mapper)
    {
        _uow = uow;
    }

然后使用UoW获取存储库来执行查询:

代码语言:javascript
复制
var repo = _unitOfWork.PartyRepository;
var p = repo.GetItems(p => Ids.Contains(someValue));

当插入或更新完成时,我可以调用SaveChanges:

代码语言:javascript
复制
_unitOfWork.SaveChanges();

这对于数据检索非常有用,但是对于数据持久性,我遇到了一个障碍。在本地域方面,我希望逐个遍历对象,保存更改或插入并调用SaveChanges以持久。如果发生错误,我将其存储在一个结果对象中,在每个同步步骤的末尾记录,然后继续到下一个对象上进行工作。

但是,由于我的应用程序目前是结构化的,如果在SaveChanges上发生了数据库异常,验证错误将一直保留在上下文中,直到它被释放。由于这个上下文被注入到UoW类中的每个存储库中,所以它仍然存在于我认为是整个同步过程的生命周期中。

在使用WindowsService托管的TopShelf中,我将Autofac用于DI,并将TopShelf注册为:

代码语言:javascript
复制
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().WithParameter("context", new EntityModel());

以下是我的问题:

  1. 应否将此问题张贴于守则审查:)
  2. 我觉得我应该用UoW反转我的存储库,将UoW传递到每个存储库,将我的存储库传递给每个服务(服务可以使用多个存储库)。
  3. 是否有必要为每个DbContext设置一个新的SaveChanges,并将一个DbContext (该DbContext传递给UoW)作为我的读取上下文,并将所有其他上下文作为SavingChanges时的新内容?

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

发布于 2015-03-12 22:34:05

  1. 不困扰我,我只使用它,也不打算去其他地方,也不介意有这样的问题。
  2. 我强烈建议您的IRepository服务和存储库请求IUoW。我甚至认为IRepository不仅仅是EF的障碍。我通常只使用一个存储库,如果任何一个
    • 我事先知道,我将实现一个非EF存储库,否则
    • 我想实现一些实际的逻辑,我希望从我的服务中抽象出来,而不会使它成为通用的。例如,我将创建一个UserProfileRepository,它将具有诸如SyncCurrentUserProfile之类的方法,而不是公开Add/Insert/Update。如果我不打算使用基于非EF的模型,那么公开Add/Insert/Update对方程没有任何影响。

  1. 那得看情况。如果你不使用跟踪,而且随着时间的推移有很多不相关的变化。当您每次添加/更新某个内容时,它都会将其添加到上下文中,这会导致以后的添加/修改变得更慢。但是,如果您要到处添加/修改10件东西,除非每次都需要一个新的上下文,否则可能不会担心。

我实际上是在写一篇关于这个的博客文章。稍后将尝试发布一个链接。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29020807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档