我目前正在创建一个实现存储库模式的概念验证应用程序。我决定使用经典ADO.NET 和实体框架作为我的示例ORM。目前这是我的IRepository和IUnitOfWork接口的实现方式。
public interface IUnitOfWork : IDisposable
{
IEmployeeRepository Employees { get; }
int Complete();
}
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(int id);
IEnumerable<TEntity> GetAll();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate);
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
}
我的Entity Framework实现完全可以更新对象,因为它有一个内置的 ChangeTracker 类来检查对象的状态。
static void Main(string[] args)
{
var context = new RPContextDbFactory().CreateDbContext(null);
using (var unitOfWork = new Data.EF.UnitOfWork(context))
{
//using Entity Framework
var employee = unitOfWork.Employees
.Get(1);
employee.FirstName = "Foo";
unitOfWork.Complete(); // <-- Calls DbContext.SaveChanges()
}
}
我的问题是我如何在经典的ADO.NET实现上实现相同的概念,因为它没有像EF这样的ChangeTracker类。
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
IConfigurationRoot configuration = builder.Build();
var connectionString = configuration.GetConnectionString("RPContext");
using (var unitOfWork = new Data.StoredProcedures.UnitOfWork(connectionString))
{
//using classic ADO.NET
var employee = unitOfWork.Employees
.Get(1);
employee.FirstName = "Foo";
unitOfWork.Complete(); //<-- Nothing will happen.
}
}
//UnitOfWork implementation for my classic ADO.NET
public class UnitOfWork : IUnitOfWork
{
public UnitOfWork(string connectionString)
{
Employees = new EmployeeRepository(connectionString);
}
public IEmployeeRepository Employees { get; private set; }
public int Complete()
{
throw new NotImplementedException();
}
public void Dispose()
{
throw new NotImplementedException();
}
}
我在其他网站上看到的一个建议是在我的ADO.NET命名空间的UnitOfWork类中实现ChangeTracker逻辑,但我不确定如何实现它。我的UoW将如何知道哪些对象被更改了?
答案 0 :(得分:1)
我不明白是否需要同时使用ADO.NET和EF。仅EF应该这样做。
无论如何,我建议不要自己为ADO.NET实现UoW。它的大量工作和容易出错,最后你会发现你做错了。如果您真的想使用UoW,请使用EF(或NHibernate或其他)。为什么重新发明轮子?如果你决定自己实现它,你实际上是在编写自己的ORM,它被认为是anti pattern。
如果您想使用ADO.NET实现UPDATE功能,那么您只需在void Update(TEntity entity);
中实现IRepository
方法,并通过调用代码显式调用它。不要让IUnitOfWork
自动执行此操作。
编辑:回复您的部分评论
经典的ADO.NET ORM没有此功能,这就是我在更新对象时遇到问题的原因。
ADO.NET不是ORM。它是与RDBMS通信的简单核心API。所有ORM都在内部使用它。
它也破坏了存储库模式的一个关键目的,即将应用程序与任何ORM框架分离。
不,隐藏ORM不是Repository的目标。抽象数据库逻辑是。通过这样做,您可以模拟存储库,并且您的其他代码变得可测试。切换ORM是非常罕见的决定。存储库使该过程变得简单;当然。但是,它仍然不是Repository的责任。实际上,Repository与ORM无关。
仍然必须为所有这些实现存储库模式。
可能是;取决于业务需求。像EF这样的完整ORM本身就是Repository。因此,设计决定是否在其上再添加一个抽象。有些人会加上它;有些人喜欢直接使用ORM。这两种方法都有其优点和缺点。
创建Update方法不正确,因为您的存储库不应该关注数据库的语义。
您必须自己实施ORM。许多ORM都是开源的。请参阅Git Hub上的Dapper-Contrib代码。它支持有限的UoW;好开始。希望它可以帮助你。
我仍然坚持(根据我自己的经验)不发展自己的ORM。