我正在编写Salesforce环境和本地环境之间的同步服务。由于每天对# of API请求的限制,我使用Salesforce API纯粹是在批处理级别上,尽管我确实有原子级故障的详细信息。但是,我希望在本地环境中保存原子级的更改,因为如果一个实体失败,我不希望整个事务失败。
我正在使用实体框架6和一个工作单元和仓库模式。下面是我的相关代码(实现细节如下):
IUnitOfWork
public interface IUnitOfWork: IDisposable
{
IReadUpdateRepository<EntityType1> EntityType1Repository { get; }
ISyncRepository<EntityType2> EntityType2Repository { get; }
ISyncRepository<EntityType3> EntityType3Repository { get; }
...other repos
void SaveChanges();
}IUnitOfWork的实现
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
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的实现
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注入其中:
private readonly IUnitOfWork _uow;
public EntityDataService(IUnitOfWork uow, ICamsSfDTOMapper mapper)
{
_uow = uow;
}然后使用UoW获取存储库来执行查询:
var repo = _unitOfWork.PartyRepository;
var p = repo.GetItems(p => Ids.Contains(someValue));当插入或更新完成时,我可以调用SaveChanges:
_unitOfWork.SaveChanges();这对于数据检索非常有用,但是对于数据持久性,我遇到了一个障碍。在本地域方面,我希望逐个遍历对象,保存更改或插入并调用SaveChanges以持久。如果发生错误,我将其存储在一个结果对象中,在每个同步步骤的末尾记录,然后继续到下一个对象上进行工作。
但是,由于我的应用程序目前是结构化的,如果在SaveChanges上发生了数据库异常,验证错误将一直保留在上下文中,直到它被释放。由于这个上下文被注入到UoW类中的每个存储库中,所以它仍然存在于我认为是整个同步过程的生命周期中。
在使用WindowsService托管的TopShelf中,我将Autofac用于DI,并将TopShelf注册为:
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().WithParameter("context", new EntityModel());以下是我的问题:
任何帮助都将不胜感激。
发布于 2015-03-12 22:34:05
IRepository服务和存储库请求IUoW。我甚至认为IRepository不仅仅是EF的障碍。我通常只使用一个存储库,如果任何一个SyncCurrentUserProfile之类的方法,而不是公开Add/Insert/Update。如果我不打算使用基于非EF的模型,那么公开Add/Insert/Update对方程没有任何影响。
我实际上是在写一篇关于这个的博客文章。稍后将尝试发布一个链接。
https://stackoverflow.com/questions/29020807
复制相似问题