c#中多个属性的搜索条件
本文关键字:搜索 条件 属性 | 更新日期: 2023-09-27 18:03:04
我想对多个属性执行搜索条件,但是,我遇到了一个问题。如果某些属性为空或null,这不是搜索条件的一部分,请帮助我..这里是下面的代码:
public List<AccountDto> getSearchedAccount(int accountid,int userid,String holdername,String type,double balance,String status)
{
List<AccountDto> results = new List<AccountDto>();
for (int i = 0; i < list.Count; i++)
{
AccountDto dto = (AccountDto)list[i];
if ((dto.Accountid == accountid) && (dto.Userid==userid) && (dto.Holdername.Equals(holdername)) && (dto.Balance == balance) && (dto.Status.Equals(status)) )
{
results.Add(dto);
}
}
return results;
}
请告诉我正确的if语句是一些字段是空的或空的,没有出现在搜索条件。
就像这样:
if (accountid < 0 || dto.Accountid == accountid)
&& ...
&& (string.IsNullOrEmpty(holdername) || dto.Holdername.Equals(holdername))
&& ... )
{
results.Add(dto);
}
为每个条件引入一个或,如果未设置值或比较重要,则该条件为真。例如,如果holdername为null或空,则不会计算holdername的等号。
为什么不创建一个方法呢?在该方法中,您可以检查属性是否为null
或空或其他任何内容。
private bool CheckAccount(AccountDto dto, int accountid, int userid, String holdername, string type, double balance, String status){
bool isTrue = true;
...
if(holdername != null){
if(!dto.Holdername.Equals(holdername))
return false;
}
...
return true; //all properties are true
}
我想这可能是你正在寻找的:c# Coalesce
可以在搜索条件中构建聚合过滤器。我认为下面的帖子有相同的你正在寻找。试试这个
我可能会检查default(type)和string.IsNullOrEmpty(…)
所以你可以写:
public List<AccountDto> getSearchedAccount(int accountid, int userid, string holdername, string type, double balance, string status)
{
var results = new List<AccountDto>();
for (int i = 0; i < list.Count; i++)
{
AccountDto dto = (AccountDto)list[i];
if (accountid != default(int) && accountid != dto.Accountid)
continue;
if (userid != default(int) && userid != dto.Userid)
continue;
if (!string.IsNullOrEmpty(holdername) && !holdername.Equals(dto.Holdername))
continue;
if (!string.IsNullOrEmpty(type) && !type.Equals(dto.Type))
continue;
if (balance != default(double) && balance != dto.Balance)
continue;
if (!string.IsNullOrEmpty(status) && !status.Equals(dto.Status))
continue;
results.Add(dto);
}
return results;
}
或者使用表达式树
public List<AccountDto> getSearchedAccount(int accountid, int userid, string holdername, string type, double balance, string status)
{
IQueryable<AccountDto> query = list.AsQueryable();
if (accountid != default(int))
query = query.Where(i => i.Accountid.Equals(accountid));
if (userid != default(int))
query = query.Where(i => i.Userid.Equals(userid));
if (!string.IsNullOrEmpty(holdername))
query = query.Where(i => i.Holdername.Equals(holdername));
if (!string.IsNullOrEmpty(holdername))
query = query.Where(i => i.Type.Equals(type));
if (balance != default(double))
query = query.Where(i => i.Balance.Equals(balance));
if (!string.IsNullOrEmpty(holdername))
query = query.Where(i => i.Status.Equals(status));
return query.Select(i => i).ToList<AccountDto>();
}
几点思考
- 我确定你的意思是使用小数的货币值,而不是双精度。
创建一个对象来表示您的标准,这样您就不必每次决定添加新字段时都更改方法签名
public List getSearchedAccount(accountsearchcriteria){…}
/*** Answer with the comments in code ***/
// don't create a class to represent your criteria
// Dictionary is enough for use and supported by Linq
// don't use a lot of `&&` or `if`; one `if` is enough
// all the rules is in deferred execution, only executes when it really needs
// evaluated and the order to put where clauses matters, don't make it changed
// it performs like short-circuit evaluation
/// <summary>
/// declared as partial for easily coexists with original code
/// if not used(e.g already declared) then not paste to file
/// </summary>
partial class AccountDto /* known members */ {
public int Accountid;
public int Userid;
public String Holdername;
public int Balance;
public String Status;
}
/// <summary>
/// declared as partial for easily coexists with original code
/// if getSearchedAccount is declared with another class name
/// then just rename the partial class to that name and remove
/// all `static`(if that class is non-static)
/// the class initializer, then become constructor; remember to
/// match the name of class and constructor
/// </summary>
partial class AccountDto {
/// <summary>
/// declare as static for this demo;
/// not necessarily be static if it's declared in another
/// class where list is declared
/// </summary>
public static List<AccountDto> getSearchedAccount(
int accountid, int userid,
String holdername, String type,
double balance,
String status
) {
var results=new List<AccountDto>();
// make a copy of IgnoreRules and clear; equivalent to
// var matchRules=new Dictionary<String, Func<AccountDto, bool>>();
// IgnoreRules is not changed with these two statement
// just prevent to see too many angle braces
var matchRules=IgnoreRules.ToDictionary(x => x.Key, x => x.Value);
matchRules.Clear();
// the parameters only known in this method thus can only added here
matchRules.Add("accountid", x => accountid==x.Accountid);
matchRules.Add("userid", x => userid==x.Userid);
matchRules.Add("holdername", x => holdername==x.Holdername);
matchRules.Add("balance", x => balance==x.Balance);
matchRules.Add("status", x => status==x.Status);
for(int i=0; i<list.Count; i++) {
var dto=(AccountDto)list[i];
if((from ignoreRule in IgnoreRules
from matchRule in matchRules
where ignoreRule.Key==matchRule.Key
where !ignoreRule.Value(dto)
select matchRule.Value(dto)).All(x => x))
results.Add(dto);
}
return results;
}
/// <summary>
/// criteria for `don't test for matching`
/// </summary>
public static Dictionary<String, Func<AccountDto, bool>> IgnoreRules {
get;
set;
}
/// <summary>
/// use class initializer to add common IgnoreRules
/// </summary>
static AccountDto() {
IgnoreRules=new Dictionary<String, Func<AccountDto, bool>>();
IgnoreRules.Add("accountid", x => 0==x.Accountid);
IgnoreRules.Add("userid", x => 0==x.Userid);
IgnoreRules.Add("holdername", x => String.IsNullOrEmpty(x.Holdername));
IgnoreRules.Add("balance", x => 0==x.Balance);
IgnoreRules.Add("status", x => String.IsNullOrEmpty(x.Status));
}
/// <summary>
/// declare as static for this demo;
/// not necessarily be static if it's declared in another
/// class where getSearchedAccount is declared
/// </summary>
public static List<AccountDto> list=new List<AccountDto>();
}