使用 Dapper 在数据库中执行动态实体
Execute Dynamic Entity in Database using Dapper
我的用户从客户端项目发送动态实体,所以我必须编写这样的方法
public Task<TUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
throw new NotImplementedException();
//string sql = "SELECT * FROM \"IdentityUsers\" WHERE \"NormalizedUserName\" = @NormalizedUserName;";
//using (var connection = _databaseConnectionFactory.CreateConnectionAsync())
//{
// connection.QueryFirstOrDefaultAsync<TUser>(sql,
// new { NormalizedUserName = normalizedUserName });
//}
}
我的 IDatabaseConnectionFactory class 像下面那样绑定 ConnectionString:
public interface IDatabaseConnectionFactory
{
Task<IDbConnection> CreateConnectionAsync();
}
public class ConnectionFactory : IDatabaseConnectionFactory
{
private readonly string _connectionString;
public ConnectionFactory(string connectionString) => _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
public async Task<IDbConnection> CreateConnectionAsync()
{
try
{
var connString = new NpgsqlConnection(_connectionString);
await connString.OpenAsync();
return connString;
}
catch
{
throw;
}
}
}
现在,我如何使用通用类型实体执行以下查询 TUser
string sql = "SELECT * FROM \"IdentityUsers\" WHERE \"NormalizedUserName\" = @NormalizedUserName;";
using (var connection = _databaseConnectionFactory.CreateConnectionAsync())
{
connection.QueryFirstOrDefaultAsync<TUser>(sql,
new { NormalizedUserName = normalizedUserName });
}
注意:QueryFirstOrDefaultAsync 未在此处的连接下找到
您不是在等待 CreateConnectionAsync
。不幸的是,在这种情况下并不明显,因为 Task<T>
是一次性的(所以 using
不会抱怨);试试看:
using (var connection = await _databaseConnectionFactory.CreateConnectionAsync())
{
var user = await connection.QueryFirstOrDefaultAsync<TUser>(sql,
new { NormalizedUserName = normalizedUserName });
}
提示:编译器输出(针对原始代码)有助于说明这一点:
Error CS1929 'Task<IDbConnection>
' does not contain a definition for 'QueryFirstOrDefaultAsync
' and the best extension method overload 'SqlMapper.QueryFirstOrDefaultAsync<TUser>(IDbConnection, string, object, IDbTransaction, int?, CommandType?)
' requires a receiver of type 'IDbConnection
'
这告诉我们:
- 找到了一些
QueryFirstOrDefaultAsync
方法,但是不能用,因为
- 目标表达式是
Task<IDbConnection>
,而不是 IDbConnection
附带说明:值得一提的是,如果您只对连接执行一项操作,Dapper 可以为您处理打开和关闭连接——这有助于减少 async/await 操作。考虑一下,例如,如果您有一个 CreateClosedConnection()
方法 没有 打开连接,因此不需要异步;以下仍然有效:
using (var connection = _databaseConnectionFactory.CreateClosedConnection())
{
var user = await connection.QueryFirstOrDefaultAsync<TUser>(sql,
new { NormalizedUserName = normalizedUserName });
}
作为 QueryFirstOrDefaultAsync
的一部分,Dapper 会为您处理 await OpenAsync()
。
我的用户从客户端项目发送动态实体,所以我必须编写这样的方法
public Task<TUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
throw new NotImplementedException();
//string sql = "SELECT * FROM \"IdentityUsers\" WHERE \"NormalizedUserName\" = @NormalizedUserName;";
//using (var connection = _databaseConnectionFactory.CreateConnectionAsync())
//{
// connection.QueryFirstOrDefaultAsync<TUser>(sql,
// new { NormalizedUserName = normalizedUserName });
//}
}
我的 IDatabaseConnectionFactory class 像下面那样绑定 ConnectionString:
public interface IDatabaseConnectionFactory
{
Task<IDbConnection> CreateConnectionAsync();
}
public class ConnectionFactory : IDatabaseConnectionFactory
{
private readonly string _connectionString;
public ConnectionFactory(string connectionString) => _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
public async Task<IDbConnection> CreateConnectionAsync()
{
try
{
var connString = new NpgsqlConnection(_connectionString);
await connString.OpenAsync();
return connString;
}
catch
{
throw;
}
}
}
现在,我如何使用通用类型实体执行以下查询 TUser
string sql = "SELECT * FROM \"IdentityUsers\" WHERE \"NormalizedUserName\" = @NormalizedUserName;";
using (var connection = _databaseConnectionFactory.CreateConnectionAsync())
{
connection.QueryFirstOrDefaultAsync<TUser>(sql,
new { NormalizedUserName = normalizedUserName });
}
注意:QueryFirstOrDefaultAsync 未在此处的连接下找到
您不是在等待 CreateConnectionAsync
。不幸的是,在这种情况下并不明显,因为 Task<T>
是一次性的(所以 using
不会抱怨);试试看:
using (var connection = await _databaseConnectionFactory.CreateConnectionAsync())
{
var user = await connection.QueryFirstOrDefaultAsync<TUser>(sql,
new { NormalizedUserName = normalizedUserName });
}
提示:编译器输出(针对原始代码)有助于说明这一点:
Error CS1929 '
Task<IDbConnection>
' does not contain a definition for 'QueryFirstOrDefaultAsync
' and the best extension method overload 'SqlMapper.QueryFirstOrDefaultAsync<TUser>(IDbConnection, string, object, IDbTransaction, int?, CommandType?)
' requires a receiver of type 'IDbConnection
'
这告诉我们:
- 找到了一些
QueryFirstOrDefaultAsync
方法,但是不能用,因为 - 目标表达式是
Task<IDbConnection>
,而不是IDbConnection
附带说明:值得一提的是,如果您只对连接执行一项操作,Dapper 可以为您处理打开和关闭连接——这有助于减少 async/await 操作。考虑一下,例如,如果您有一个 CreateClosedConnection()
方法 没有 打开连接,因此不需要异步;以下仍然有效:
using (var connection = _databaseConnectionFactory.CreateClosedConnection())
{
var user = await connection.QueryFirstOrDefaultAsync<TUser>(sql,
new { NormalizedUserName = normalizedUserName });
}
作为 QueryFirstOrDefaultAsync
的一部分,Dapper 会为您处理 await OpenAsync()
。