c# - 更新存储库模式的概念

标签 c# .net-core repository-pattern

我目前正在创建一个实现存储库模式的概念验证应用程序。我决定使用经典 ADO.NET Entity Framework 作为我的示例 ORM。这就是我目前的 IRepository 和 IUnitOfWork 接口(interface)的实现方式。

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 如何知道哪些对象已更改?

最佳答案

我不明白同时使用 ADO.NET 和 EF 的必要性。单独使用 EF 就可以了。

无论如何,我建议不要自己为 ADO.NET 实现 UoW。它的工作量很大,而且容易出错,最后你会发现你做错了。如果您确实想使用 UoW,请改用 EF(或 NHibernate 或其他)。为什么要重新发明轮子?如果您决定自己实现它,那么您实际上是在编写自己的 ORM,它被视为 anti pattern .

如果您想使用 ADO.NET 实现 UPDATE 功能,那么您只需在 IRepository 中实现 void Update(TEntityEntity); 方法并从调用代码。不要让 IUnitOfWork 自动执行此操作。

编辑:回复您的一些评论 -

The classic ADO.NET ORM does not have this feature which is why I am having problems with updating objects.

ADO.NET 不是 ORM。它是与 RDBMS 通信的简单且核心的 API。所有 ORM 在内部都使用它。

it also defeats one of the key purpose of the repository pattern which is to decouple your application from any ORM frameworks.

不,隐藏 ORM 不是 Repository 的目标。抽象数据库逻辑。通过这样做,您可以模拟存储库,并且您的其他代码变得可测试。切换 ORM 是相当罕见的决定。存储库使这个过程变得简单;当然。但这仍然不是存储库的责任。实际上,Repository 与 ORM 无关。

Repository pattern must still be implemented for all of them.

可能是;取决于业务需求。像 EF 这样的完整 ORM 本身就是存储库。因此,是否在其上添加更多抽象是设计决策。有些人确实添加了它;有些人则添加了它。有些人更喜欢直接使用 ORM。两种方法都有优点和缺点。

Creating an Update method is incorrect because your repository should not concern itself with the semantics of your database.

那么你必须自己实现 ORM。许多 ORM 都是开源的。请参阅 Git Hub 上的 Dapper-Contrib 代码。它支持有限的UoW;很好开始。希望对您有帮助。

我仍然坚持(根据我自己的经验)不要开发自己的 ORM。

关于c# - 更新存储库模式的概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50731983/

相关文章:

linq-to-sql - 在基于 LINQ to SQL 的存储库中,我们是否应该在每个方法中创建一个新的 DataContext?

entity-framework - 用于更新整个聚合的通用存储库

c# - Entity Framework - 使用 View 加载过多数据

c# - 事件真的让代码解耦了吗?

c# - 从下拉列表中选择值并单击按钮时如何从数据库中删除

c# - 如何设置 ffmpeg 管道输出?

c# - FormatterServices.GetUninitializedObject(type) UWP/NETCore 等效

google-chrome - 如何将 "allow-downloads"添加到沙箱属性列表中

c# - 具有通用基类的ASP.NET Core 2.0存储库模式

c# - 如何将 unicode(阿拉伯语)字符插入 SQL Server 数据库