Ctr*_*eat 17 .net c# design-patterns repository-pattern dapper
这可能是代码审查的问题,而不是堆栈溢出.
我正在使用Dapper for MicroORM来检索并将数据保存到SQL Server 2014.我在DTO Proj中有DTO类,它代表从DB检索到的数据或保存到DB.
我正在使用存储库模式,所以在我的服务层,如果需要存储库,我使用构造函数DI来注入该依赖项,然后调用存储库上的方法来完成工作.
所以假设我有2个名为CustomerService和CarService的服务.
然后,我有2个存储库,一个CustomerRepository和一个CarRepository.
我有一个接口,它定义每个存储库中的所有方法,然后定义具体的实现.
下面显示了一个示例方法(调用Stored Proc来执行DB INSERT(注意存储过程的实际字符串变量被定义为类顶部的私有字符串):
public void SaveCustomer(CustomerDTO custDTO)
{
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
{
db.Execute(saveCustSp, custDTO, commandType: CommandType.StoredProcedure);
}
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好但我发现自己在每个存储库中的每个方法中重复使用块.我有两个真正的问题,如下所述.
有没有更好的方法,我可能会以某种方式使用BaseRepository类,每个其他存储库继承,Base将实现数据库连接的实例化?
对于系统上的多个并发用户,这仍然可以正常工作吗?
********更新
根据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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,在我的存储库中,我有其他方法,如下所示:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
和
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);
}
}
Run Code Online (Sandbox Code Playgroud)
使用Generic Type T将这些添加到我的Base存储库的正确方法是什么,这样我就可以返回任何类型的DTO或任何C#Native类型
Sil*_*gel 19
当然,创建和部署Connection的功能非常有用.
protected void Execute(Action<IDbConnection> query)
{
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
{
query.Invoke(db);
}
}
Run Code Online (Sandbox Code Playgroud)
你简化的通话网站:
public void SaveCustomer(CustomerDTO custDTO)
{
Execute(db => db.Execute(saveCustSp, custDTO, CommandType.StoredProcedure));
}
Run Code Online (Sandbox Code Playgroud)
使用返回值:
public T Get<T>(Func<IDbConnection, T> query)
{
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
{
return query.Invoke(db);
}
}
Run Code Online (Sandbox Code Playgroud)
在您的呼叫站点中,只需编写您要使用的逻辑.
public IEnumerable<EmployeeDTO> GetEmployeeDetails(int employeeId)
{
return Get<IEnumerable<EmployeeDTO>(db =>
db.Query<EmployeeDTO>(anotherSp, new { EmployeeID = employeeId }, CommandType.StoredProcedure));
}
Run Code Online (Sandbox Code Playgroud)
这与您的问题没有直接关系.但我建议你考虑使用DapperExtensions.
最初,我确实使用Dapper实现了Repository模式.缺点是,我必须全面编写查询; 它非常古怪.由于硬编码查询,几乎不可能编写通用存储库.
最近,我升级了我的代码以使用DapperExtensions.这解决了很多问题.
以下是通用存储库:
public abstract class BaseRepository<T> where T : BasePoco
{
internal BaseRepository(IUnitOfWork unitOfWork)
{
dapperExtensionsProxy = new DapperExtensionsProxy(unitOfWork);
}
DapperExtensionsProxy dapperExtensionsProxy = null;
protected bool Exists()
{
return (GetCount() == 0) ? false : true;
}
protected int GetCount()
{
var result = dapperExtensionsProxy.Count<T>(null);
return result;
}
protected T GetById(Guid id)
{
var result = dapperExtensionsProxy.Get<T>(id);
return result;
}
protected T GetById(string id)
{
var result = dapperExtensionsProxy.Get<T>(id);
return result;
}
protected List<T> GetList()
{
var result = dapperExtensionsProxy.GetList<T>(null);
return result.ToList();
}
protected void Insert(T poco)
{
var result = dapperExtensionsProxy.Insert(poco);
}
protected void Update(T poco)
{
var result = dapperExtensionsProxy.Update(poco);
}
protected void Delete(T poco)
{
var result = dapperExtensionsProxy.Delete(poco);
}
protected void DeleteById(Guid id)
{
T poco = (T)Activator.CreateInstance(typeof(T));
poco.SetDbId(id);
var result = dapperExtensionsProxy.Delete(poco);
}
protected void DeleteById(string id)
{
T poco = (T)Activator.CreateInstance(typeof(T));
poco.SetDbId(id);
var result = dapperExtensionsProxy.Delete(poco);
}
protected void DeleteAll()
{
var predicateGroup = new PredicateGroup { Operator = GroupOperator.And, Predicates = new List<IPredicate>() };
var result = dapperExtensionsProxy.Delete<T>(predicateGroup);//Send empty predicateGroup to delete all records.
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码中看到的,大多数方法只是基础DapperExtensionsProxy
类的包装.DapperExtensionsProxy
内部还管理UnitOfWork,您可以在下面看到.这两个类可以毫无问题地组合在一起.我个人更喜欢将它们分开.
您还可以注意到其他方法Exists
,DeleteById
并且DeleteAll
实现了那些不属于的方法DapperExtensionsProxy
.
poco.SetDbId
在每个POCO类中定义方法以设置其Identifier属性.就我而言,POCO的标识符可能具有不同的数据类型和名称.
以下是DapperExtensionsProxy
:
internal sealed class DapperExtensionsProxy
{
internal DapperExtensionsProxy(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
IUnitOfWork unitOfWork = null;
internal int Count<T>(object predicate) where T : BasePoco
{
var result = unitOfWork.Connection.Count<T>(predicate, unitOfWork.Transaction);
return result;
}
internal T Get<T>(object id) where T : BasePoco
{
var result = unitOfWork.Connection.Get<T>(id, unitOfWork.Transaction);
return result;
}
internal IEnumerable<T> GetList<T>(object predicate, IList<ISort> sort = null, bool buffered = false) where T : BasePoco
{
var result = unitOfWork.Connection.GetList<T>(predicate, sort, unitOfWork.Transaction, null, buffered);
return result;
}
internal IEnumerable<T> GetPage<T>(object predicate, int page, int resultsPerPage, IList<ISort> sort = null, bool buffered = false) where T : BasePoco
{
var result = unitOfWork.Connection.GetPage<T>(predicate, sort, page, resultsPerPage, unitOfWork.Transaction, null, buffered);
return result;
}
internal dynamic Insert<T>(T poco) where T : BasePoco
{
var result = unitOfWork.Connection.Insert<T>(poco, unitOfWork.Transaction);
return result;
}
internal void Insert<T>(IEnumerable<T> listPoco) where T : BasePoco
{
unitOfWork.Connection.Insert<T>(listPoco, unitOfWork.Transaction);
}
internal bool Update<T>(T poco) where T : BasePoco
{
var result = unitOfWork.Connection.Update<T>(poco, unitOfWork.Transaction);
return result;
}
internal bool Delete<T>(T poco) where T : BasePoco
{
var result = unitOfWork.Connection.Delete<T>(poco, unitOfWork.Transaction);
return result;
}
internal bool Delete<T>(object predicate) where T : BasePoco
{
var result = unitOfWork.Connection.Delete<T>(predicate, unitOfWork.Transaction);
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是BasePoco
上面使用的:
public abstract class BasePoco
{
Guid pocoId = Guid.NewGuid();
public Guid PocoId { get { return pocoId; } }
public virtual void SetDbId(object id)
{//Each POCO should override this method for specific implementation.
throw new NotImplementedException("This method is not implemented by Poco.");
}
public override string ToString()
{
return PocoId + Environment.NewLine + base.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
这也使用UnitOfWork,这里解释.
归档时间: |
|
查看次数: |
21596 次 |
最近记录: |