Reputation: 33
I want to perform search criteria on multiple properties but, I am having a problem. If some property is empty or null which is not part of search criteria please help me..here is the code below :
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;
}
Please tell me the correct if statement is some field is null or empty which doesn't come in search criteria.
Upvotes: 2
Views: 1956
Reputation: 4693
/*** 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>();
}
Upvotes: 0
Reputation: 18379
I'd probably check against default(type) and string.IsNullOrEmpty(...)
So you would could have:
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;
}
Or making use of an expression tree
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>();
}
Couple of thoughts
Create an object to represent your criteria so that you're not having to change the method signature every time you decide to add a new field
public List getSearchedAccount(AccountSearchCritera criteria) { ... }
Upvotes: 1
Reputation: 6563
You can build aggregate filter in search criteria. I think below post has same what you are looking for. Try This
Upvotes: 0
Reputation: 13207
Why don't you create a method for that? In that method you can check if the property is null
or empty or anything else.
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
}
Upvotes: 3
Reputation: 17631
It would go like this:
if (accountid < 0 || dto.Accountid == accountid)
&& ...
&& (string.IsNullOrEmpty(holdername) || dto.Holdername.Equals(holdername))
&& ... )
{
results.Add(dto);
}
Introduce an or for each condition which is true if the value is not set or the comparision matters. For example, if holdername is null or empty then the Equals of Holdername will not be evaluated.
Upvotes: 4