Сначала я предполагаю, что вы используете контейнер IoC. Я призываю вас создавать настоящие репозитории для каждого типа сущностей. Это означает, что вы будете заключать каждый объектный объект EntitySet в класс, который реализует что-то вроде:
interface IRepository<TEntity> {
TEntity Get(int id);
void Add(TEntity entity);
void Save(TEntity entity);
void Remove(TEntity entity);
bool CanPersist<T>(T entity);
}
CanPersist просто возвращает, поддерживает ли этот экземпляр хранилища сохранение переданной сущности, и используется ли он полиморфно UnitOfWork.Save, описанным ниже.
Каждый IRepository также будет иметь конструктор, который позволяет создавать IRepository в «транзакционном» режиме. Так, для EF, мы могли бы иметь:
public partial EFEntityARepository : IRepository<EntityA> {
public EFEntityARepository(EFContext context, bool transactional) {
_context = context;
_transactional = transactional;
}
public void Add(EntityA entity) {
_context.EntityAs.Add(entity);
if (!_transactional) _context.SaveChanges();
}
}
UnitOfWork должен выглядеть так:
interface UnitOfWork {
void Add(TEntity entity);
void Save(TEntity entity);
void Remove(TEntity entity);
void Complete();
}
Реализация UnitOfWork будет использовать внедрение зависимостей для получения экземпляров всего IRepository. В UnitOfWork.Save/Add/Remove UoW передает объект аргумента в CanPerist каждого IRepository. Для любых возвращаемых значений true
UnitOfWork будет хранить эту сущность в частной коллекции, специфичной для этого IRepository и для предполагаемой операции. В завершение UnitOfWork проверит все коллекции частных объектов и вызовет соответствующую операцию в соответствующем IRepository для каждого объекта.
Если у вас есть сущность, которая должна быть частично сохранена в EF, а частично сохранена в AD, у вас будет два класса IRepository для этого типа сущности (они оба вернут true из CanPersist при передаче экземпляра этого типа сущности).
Что касается поддержания атомарности между EF и AD, то это отдельная нетривиальная проблема.