c# - 如何使用 Dapper 实现通用存储库设计模式?

标签 c# .net design-patterns repository-pattern dapper

我正在为 MicroORM 使用 Dapper 来检索数据并将其保存到 SQL Server 2014。我在 DTO Proj 中有 DTO 类,代表从数据库检索或保存到数据库的数据。

我正在使用存储库模式,因此如果需要存储库,我会在我的服务层使用构造函数 DI 来注入(inject)该依赖项,然后调用存储库上的方法来完成工作。

假设我有 2 个服务,分别称为 CustomerService 和 CarService。

然后我有 2 个存储库,一个 CustomerRepository 和一个 CarRepository。

我有一个接口(interface),它定义了每个 Repository 中的所有方法,然后是具体的实现。

示例方法如下所示(调用存储过程执行 DB INSERT(注意存储过程的实际字符串变量在类顶部定义为私有(private)字符串):

    public void SaveCustomer(CustomerDTO custDTO)
    {
        using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
        {
            db.Execute(saveCustSp, custDTO, commandType: CommandType.StoredProcedure);
        }
    }

一切正常,但我发现自己在每个存储库的每个方法中重复使用 block 。下面列出了两个真正的问题。

是否有更好的方法我可以使用,也许以某种方式使用 BaseRepository 类,每个其他 Repository 都继承自该类,而 Base 将实现 DB 连接的实例化?

对于系统上的多个并发用户,这仍然可以正常工作吗?


根据 Silas 的回答,我创建了以下内容

public interface IBaseRepository
{
    void Execute(Action<IDbConnection> query);
}

public class BaseRepository: IBaseRepository
{
        public void Execute(Action<IDbConnection> query)
        {
            using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
            {
                query.Invoke(db);
            }
        }
}

但是,在我的存储库中,我还有其他方法,例如:

    public bool IsOnlyCarInStock(int carId, int year)
    {
        using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
        {
            var car = db.ExecuteScalar<int>(anotherStoredSp, new { CarID = carId, Year = year },
                                commandType: CommandType.StoredProcedure);

            return car > 0 ? true : false;
        }
    }

    public IEnumerable<EmployeeDTO> GetEmployeeDetails(int employeeId)
    {
        using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
        {
            return db.Query<EmployeeDTO>(anotherSp, new { EmployeeID = employeeId },
                                commandType: CommandType.StoredProcedure);
        }
    }

使用通用类型 T 将这些添加到我的基本存储库的正确方法是什么,以便我可以返回任何类型的 DTO 或任何 C# native 类型

最佳答案

当然,创建和处理您的连接的功能会很好用。

protected void Execute(Action<IDbConnection> query)
{
    using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
    {
        query.Invoke(db);
    }
}

以及您的简化调用站点:

public void SaveCustomer(CustomerDTO custDTO)
{
    Execute(db => db.Execute(saveCustSp, custDTO, CommandType.StoredProcedure));
}

有返回值:

public T Get<T>(Func<IDbConnection, T> query)
{
    using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
    {
        return query.Invoke(db); 
    }
}

在您的调用站点中,只需编写您希望使用的逻辑即可。

public IEnumerable<EmployeeDTO> GetEmployeeDetails(int employeeId)
{
    return Get<IEnumerable<EmployeeDTO>(db => 
        db.Query<EmployeeDTO>(anotherSp, new { EmployeeID = employeeId }, CommandType.StoredProcedure));
}

关于c# - 如何使用 Dapper 实现通用存储库设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42957140/

相关文章:

c# - SQL 事务报告/状态

C# : Whether this approach is thread-safe

java - 理想的代码遵循德米特法则并且是可测试的(依赖注入(inject))?

c# - 不使用 XAML 绘制形状

c# - 如何使用 C# 代码运行 C# 代码?

.net - 将 HTML 转换为 PDF - 用于 ASP.net 的任何库

java - 如何使用 Singleton 类来获得多个连接?

c# - 如何将字符串数组转为int数组进行计算?

c# - 检测在cloudflare后面连接的用户IP地址

c# - 无缓冲的 XmlReader 实现