我遵循了有关带有带有EF CORE的ASP.NET内核的通用存储库模式的教程, here 例如
public class Repository<T> : IRepository<T> where T : class
{
protected readonly DbContext _dbContext;
protected readonly DbSet<T> _dbSet;
public Repository(DbContext context)
{
_dbContext = context ?? throw new
ArgumentException(nameof(context));
_dbSet = _dbContext.Set<T>();
}
public void Add(T entity)
{
_dbSet.Add(entity);
}
}
因为这是使用EF Core,所以我们只能使用它的预定义方法通过Add
方法插入数据,但是当涉及dapper时,它需要sql查询,那么我如何才能创建适合Dapper的通用接口?
答案 0 :(得分:1)
我们有一个拥有dapper通用存储库的项目,但是在项目发展之后,我们放弃了以使用dapper的真正功能。
我建议不使用通用CRUD操作而直接使用Dapper。
为了演示我们拥有的内容,我将提供一个尚未投入生产的示例代码,这将使您有一个实现自己的通用存储库的想法。
public abstract class ConnectionBase : IDbConnection
{
protected ConnectionBase(IDbConnection connection)
{
Connection = connection;
}
protected IDbConnection Connection { get; private set; }
// Verbose but necessary implementation of IDbConnection:
#region "IDbConnection implementation"
public string ConnectionString
{
get
{
return Connection.ConnectionString;
}
set
{
Connection.ConnectionString = value;
}
}
public int ConnectionTimeout
{
get
{
return Connection.ConnectionTimeout;
}
}
public string Database
{
get
{
return Connection.Database;
}
}
public ConnectionState State
{
get
{
return Connection.State;
}
}
public IDbTransaction BeginTransaction()
{
return Connection.BeginTransaction();
}
public void Close()
{
Connection.Close();
}
public IDbCommand CreateCommand()
{
return Connection.CreateCommand();
}
public void Dispose()
{
Connection.Dispose();
}
public void Open()
{
Connection.Open();
}
#endregion
}
通用存储库
public abstract class GenericRepository<T> : IRepository<T> where T : class //EntityBase, IAggregateRoot
{
private readonly string _tableName;
internal IDbConnection Connection
{
get
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["SmsQuizConnection"].ConnectionString);
}
}
public GenericRepository(string tableName)
{
_tableName = tableName;
}
internal virtual dynamic Mapping(T item)
{
return item;
}
public virtual void Add(T item)
{
using (IDbConnection cn = Connection)
{
var parameters = (object)Mapping(item);
cn.Open();
item.ID = cn.Insert<Guid>(_tableName, parameters);
}
}
public virtual void Update(T item)
{
using (IDbConnection cn = Connection)
{
var parameters = (object)Mapping(item);
cn.Open();
cn.Update(_tableName, parameters);
}
}
public virtual void Remove(T item)
{
using (IDbConnection cn = Connection)
{
cn.Open();
cn.Execute("DELETE FROM " + _tableName + " WHERE ID=@ID", new { ID = item.ID });
}
}
public virtual T FindByID(Guid id)
{
T item = default(T);
using (IDbConnection cn = Connection)
{
cn.Open();
item = cn.Query<T>("SELECT * FROM " + _tableName + " WHERE ID=@ID", new { ID = id }).SingleOrDefault();
}
return item;
}
public virtual IEnumerable<T> FindAll()
{
IEnumerable<T> items = null;
using (IDbConnection cn = Connection)
{
cn.Open();
items = cn.Query<T>("SELECT * FROM " + _tableName);
}
return items;
}
}
答案 1 :(得分:1)
@PathumLakshan的示例来自评论。提供的示例以异步方式编写,但源代码可以同步实现。无论如何,这仅是如何使用Dapper管理基础结构的说明。类Db
提供了一些用于获取数据和执行SQL查询的通用方法。例如,您可以对基本查询使用重载Get<T>(string, object)
,也可以使用Get<T>(Func<SqlConnection, SqlTransaction, int, Task<T>>
使用说QueryMultiple
。类Repository<Entity>
展示了如何查找实体Entity
的基本存储库。
public class Db : IDb
{
private readonly Func<SqlConnection> _dbConnectionFactory;
public Db(Func<SqlConnection> dbConnectionFactory)
{
_dbConnectionFactory = dbConnectionFactory ?? throw new ArgumentNullException(nameof(dbConnectionFactory));
}
public async Task<T> CommandAsync<T>(Func<SqlConnection, SqlTransaction, int, Task<T>> command)
{
using (var connection = _dbConnectionFactory.Invoke())
{
await connection.OpenAsync();
using (var transaction = connection.BeginTransaction())
{
try
{
var result = await command(connection, transaction, Constants.CommandTimeout);
transaction.Commit();
return result;
}
catch (Exception ex)
{
transaction.Rollback();
Logger.Instance.Error(ex);
throw;
}
}
}
}
public async Task<T> GetAsync<T>(Func<SqlConnection, SqlTransaction, int, Task<T>> command)
{
return await CommandAsync(command);
}
public async Task<IList<T>> SelectAsync<T>(Func<SqlConnection, SqlTransaction, int, Task<IList<T>>> command)
{
return await CommandAsync(command);
}
public async Task ExecuteAsync(string sql, object parameters)
{
await CommandAsync(async (conn, trn, timeout) =>
{
await conn.ExecuteAsync(sql, parameters, trn, timeout);
return 1;
});
}
public async Task<T> GetAsync<T>(string sql, object parameters)
{
return await CommandAsync(async (conn, trn, timeout) =>
{
T result = await conn.QuerySingleAsync<T>(sql, parameters, trn, timeout);
return result;
});
}
public async Task<IList<T>> SelectAsync<T>(string sql, object parameters)
{
return await CommandAsync<IList<T>>(async (conn, trn, timeout) =>
{
var result = (await conn.QueryAsync<T>(sql, parameters, trn, timeout)).ToList();
return result;
});
}
}
public class Repository<Entity> : IRepository<Entity>
{
protected readonly IDb _db;
public Repository(IDb db)
{
_db = db ?? throw new
ArgumentException(nameof(db));
}
public async Task Add(Entity entity)
{
await _db.ExecuteAsync("INSERT INTO ... VALUES...", entity);
}
public async Task Update(Entity entity)
{
await _db.ExecuteAsync("UPDATE ... SET ...", entity);
}
public async Task Remove(Entity entity)
{
await _db.ExecuteAsync("DELETE FROM ... WHERE ...", entity);
}
public async Task<Entity> FindByID(int id)
{
return await _db.GetAsync<Entity>("SELECT ... FROM ... WHERE Id = @id", new { id });
}
public async Task<IEnumerable<Entity>> FindAll()
{
return await _db.SelectAsync<Entity>("SELECT ... FROM ... ", new { });
}
}
可以使用其他通用方法来扩展 Db
,例如ExecuteScalar
,这是您存储库中所需的。希望对您有所帮助。