传入模型时如何使用 Dapper 构建动态 Where 子句
How do I build a dynamic Where clause with Dapper when passing in a model
我有一个示例模型,如下所示:
public class PersonModel
{
public int Id {get; set;}
public string FirstName {get; set;}
public string Lastname {get; set;}
public string City {get; set;}
}
在我的存储库中,我想创建一个在我的模型中传递的搜索方法 - 但并非所有字段都将始终被填充。我想根据模型中的字段是否已填充来创建 WHERE 和 AND。如果该字段未填充,那么我不想为其创建 WHERE 子句。
例如 - 如果我传入 FirstName = "Bob" 和 City = "Boston" 那么我希望我的搜索看起来像这样:
SELECT * FROM PersonTable WHERE FirstName = @firstName AND City = @city
因为我没有传入 Id 或 LastName,所以我不想将它们添加到查询中。如果我只是通过 City = "Boston" 那么我希望它看起来像这样:
SELECT * FROM PersonTable WHERE City = @city
我的回购方法看起来像这样
using Dapper;
public List<PersonModel> Search(PersonModel model)
{
//db = DbConnection connection
var selectSql = "SELECT * FROM PersonTable "; //build out where clause somehow
return db.Query<PersonModel>(selectSql).ToList();
}
我的问题是如何在我的回购方法中正确构建它?
bool isFirstWhereSet = false;
bool isCityWhereSet = false;
string sqlQuery = "SELECT * FROM PersonTable " ;
if (! String.IsNullOrEmpty(model.FirstName ))
{
sqlQuery =sqlQuery + "WHERE FirstName =@FirstName" ;
isFirstWhereSet = true;
}
if (! String.IsNullOrEmpty(model.City))
{
isCityWhereSet = true ;
if (! isFirstWhereSet )
sqlQuery = sqlQuery + " WHERE City = @city";
else
sqlQuery = sqlQuery + " AND City = @city";
}
if (isFirstWhereSet == true && isCityWhereSet == true )
return db.Query<PersonModel>(sqlQuery , new { FirstName = model.FirstName , City = mode.City}).ToList();
else if (isFirstWhereSet == true && isCityWhereSet == false)
return db.Query<PersonModel>(sqlQuery , new { FirstName = model.FirstName }).ToList();
else if (isFirstWhereSet == false && isCityWhereSet == true)
return db.Query<PersonModel>(sqlQuery , new { City= model.City}).ToList();
else
{
return db.Query<PersonModel>(sqlQuery).ToList();
}
这应该可以为您解决问题,简洁明了:
var selectSql = "SELECT * FROM PersonTable WHERE (@FirstName IS NULL OR FirstName = @FirstName) AND (@LastName IS NULL OR LastName = @LastName) AND (@City IS NULL OR City = @City) AND (@Id IS NULL OR Id = @Id) OPTION(RECOMPILE)";
return conn.Query<PersonModel>(selectSql, new
{
model.FirstName,
model.Lastname,
model.City,
Id = model.Id == 0? (int?)null: (int?)model.Id
}).ToList();
您也可以使用 Dapper 的 SqlBuilder。
请注意,您必须安装 Dapper.SqlBuilder NuGet 包,因为它没有随 Dapper 的主要发行版一起提供。
这是一个例子:
[Test]
public void Test()
{
var model = new PersonModel {FirstName = "Bar", City = "New York"};
var builder = new SqlBuilder();
//note the 'where' in-line comment is required, it is a replacement token
var selector = builder.AddTemplate("select * from table /**where**/");
if (model.Id > 0)
builder.Where("Id = @Id", new { model.Id });
if (!string.IsNullOrEmpty(model.FirstName))
builder.Where("FirstName = @FirstName", new { model.FirstName });
if (!string.IsNullOrEmpty(model.Lastname))
builder.Where("Lastname = @Lastname", new { model.Lastname });
if (!string.IsNullOrEmpty(model.City))
builder.Where("City = @City", new { model.City });
Assert.That(selector.RawSql, Is.EqualTo("select * from table WHERE FirstName = @FirstName AND City = @City\n"));
//var rows = sqlConnection.Query(selector.RawSql, selector.Parameters);
}
您可以找到一些示例 here。
您可以使用 ExpressionExtensionSQL 库。此库将 lambda 表达式转换为 where 子句,并可与 dapper 和 ADO 一起使用。
如果您想尝试其他选择,DapperQueryBuilder 可能更容易使用:
var query = cn.QueryBuilder($@"
SELECT *
FROM PersonTable
/**where**/
");
if (model.Id > 0)
query.Where($"Id = {model.Id}");
if (!string.IsNullOrEmpty(model.FirstName))
query.Where($"FirstName = {model.FirstName}");
if (!string.IsNullOrEmpty(model.Lastname))
query.Where($"Lastname = {model.Lastname}");
if (!string.IsNullOrEmpty(model.City))
query.Where($"City = {model.City}");
var results = query.Query<Person>();
Query<Person>()
将调用传递底层 SQL 和参数的 Dapper。
底层查询已完全参数化SQL:
WHERE FirstName = @p0 AND LastName = @p1
,等等
或者,更简单:
var query = cn.QueryBuilder($"SELECT * FROM PersonTable WHERE 1=1");
if (model.Id > 0)
query += $"AND Id = {model.Id}";
if (!string.IsNullOrEmpty(model.FirstName))
query += $"AND FirstName = {model.FirstName}";
if (!string.IsNullOrEmpty(model.Lastname))
query += $"AND Lastname = {model.Lastname}";
if (!string.IsNullOrEmpty(model.City))
query += $"AND City = {model.City}";
var results = query.Query<Person>();
免责声明:我是该库的作者之一
我有一个示例模型,如下所示:
public class PersonModel
{
public int Id {get; set;}
public string FirstName {get; set;}
public string Lastname {get; set;}
public string City {get; set;}
}
在我的存储库中,我想创建一个在我的模型中传递的搜索方法 - 但并非所有字段都将始终被填充。我想根据模型中的字段是否已填充来创建 WHERE 和 AND。如果该字段未填充,那么我不想为其创建 WHERE 子句。
例如 - 如果我传入 FirstName = "Bob" 和 City = "Boston" 那么我希望我的搜索看起来像这样:
SELECT * FROM PersonTable WHERE FirstName = @firstName AND City = @city
因为我没有传入 Id 或 LastName,所以我不想将它们添加到查询中。如果我只是通过 City = "Boston" 那么我希望它看起来像这样:
SELECT * FROM PersonTable WHERE City = @city
我的回购方法看起来像这样
using Dapper;
public List<PersonModel> Search(PersonModel model)
{
//db = DbConnection connection
var selectSql = "SELECT * FROM PersonTable "; //build out where clause somehow
return db.Query<PersonModel>(selectSql).ToList();
}
我的问题是如何在我的回购方法中正确构建它?
bool isFirstWhereSet = false;
bool isCityWhereSet = false;
string sqlQuery = "SELECT * FROM PersonTable " ;
if (! String.IsNullOrEmpty(model.FirstName ))
{
sqlQuery =sqlQuery + "WHERE FirstName =@FirstName" ;
isFirstWhereSet = true;
}
if (! String.IsNullOrEmpty(model.City))
{
isCityWhereSet = true ;
if (! isFirstWhereSet )
sqlQuery = sqlQuery + " WHERE City = @city";
else
sqlQuery = sqlQuery + " AND City = @city";
}
if (isFirstWhereSet == true && isCityWhereSet == true )
return db.Query<PersonModel>(sqlQuery , new { FirstName = model.FirstName , City = mode.City}).ToList();
else if (isFirstWhereSet == true && isCityWhereSet == false)
return db.Query<PersonModel>(sqlQuery , new { FirstName = model.FirstName }).ToList();
else if (isFirstWhereSet == false && isCityWhereSet == true)
return db.Query<PersonModel>(sqlQuery , new { City= model.City}).ToList();
else
{
return db.Query<PersonModel>(sqlQuery).ToList();
}
这应该可以为您解决问题,简洁明了:
var selectSql = "SELECT * FROM PersonTable WHERE (@FirstName IS NULL OR FirstName = @FirstName) AND (@LastName IS NULL OR LastName = @LastName) AND (@City IS NULL OR City = @City) AND (@Id IS NULL OR Id = @Id) OPTION(RECOMPILE)";
return conn.Query<PersonModel>(selectSql, new
{
model.FirstName,
model.Lastname,
model.City,
Id = model.Id == 0? (int?)null: (int?)model.Id
}).ToList();
您也可以使用 Dapper 的 SqlBuilder。
请注意,您必须安装 Dapper.SqlBuilder NuGet 包,因为它没有随 Dapper 的主要发行版一起提供。
这是一个例子:
[Test]
public void Test()
{
var model = new PersonModel {FirstName = "Bar", City = "New York"};
var builder = new SqlBuilder();
//note the 'where' in-line comment is required, it is a replacement token
var selector = builder.AddTemplate("select * from table /**where**/");
if (model.Id > 0)
builder.Where("Id = @Id", new { model.Id });
if (!string.IsNullOrEmpty(model.FirstName))
builder.Where("FirstName = @FirstName", new { model.FirstName });
if (!string.IsNullOrEmpty(model.Lastname))
builder.Where("Lastname = @Lastname", new { model.Lastname });
if (!string.IsNullOrEmpty(model.City))
builder.Where("City = @City", new { model.City });
Assert.That(selector.RawSql, Is.EqualTo("select * from table WHERE FirstName = @FirstName AND City = @City\n"));
//var rows = sqlConnection.Query(selector.RawSql, selector.Parameters);
}
您可以找到一些示例 here。
您可以使用 ExpressionExtensionSQL 库。此库将 lambda 表达式转换为 where 子句,并可与 dapper 和 ADO 一起使用。
如果您想尝试其他选择,DapperQueryBuilder 可能更容易使用:
var query = cn.QueryBuilder($@"
SELECT *
FROM PersonTable
/**where**/
");
if (model.Id > 0)
query.Where($"Id = {model.Id}");
if (!string.IsNullOrEmpty(model.FirstName))
query.Where($"FirstName = {model.FirstName}");
if (!string.IsNullOrEmpty(model.Lastname))
query.Where($"Lastname = {model.Lastname}");
if (!string.IsNullOrEmpty(model.City))
query.Where($"City = {model.City}");
var results = query.Query<Person>();
Query<Person>()
将调用传递底层 SQL 和参数的 Dapper。
底层查询已完全参数化SQL:
WHERE FirstName = @p0 AND LastName = @p1
,等等
或者,更简单:
var query = cn.QueryBuilder($"SELECT * FROM PersonTable WHERE 1=1");
if (model.Id > 0)
query += $"AND Id = {model.Id}";
if (!string.IsNullOrEmpty(model.FirstName))
query += $"AND FirstName = {model.FirstName}";
if (!string.IsNullOrEmpty(model.Lastname))
query += $"AND Lastname = {model.Lastname}";
if (!string.IsNullOrEmpty(model.City))
query += $"AND City = {model.City}";
var results = query.Query<Person>();
免责声明:我是该库的作者之一