我正在Salesforce环境和本地环境之间编写同步服务。由于每天的API请求数量限制,我对Salesforce API的使用纯粹是在批处理级别,尽管我确实有原子级故障的详细信息。但是,我想在本地环境中保存原子级别的更改,因为如果一个实体失败,我不希望整个事务失败。
我正在使用具有工作单元和存储库模式的Entity Framework 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类的每个存储库中,因此我认为它是整个同步过程的生命周期。
我在使用TopShelf托管的WindowsService中使用Autofac for DI,我正在注册我的UoW:
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().WithParameter("context", new EntityModel());
以下是我的问题:
任何帮助都将不胜感激。
答案 0 :(得分:1)
IRepository
和您的存储库请求IUoW
。我甚至认为IRepository
不仅仅是EF的障碍。我通常只使用存储库
SyncCurrentUserProfile
之类的方法,而不是公开Add/Insert/Update
。如果我不打算使用非基于EF的模型,则公开Add/Insert/Update
不会增加等式。我实际上正在写一篇关于此的博文。稍后会尝试发布链接。