开发者

How to apply multi-criteria search to LINQ?

I have a WebForm with 4 combo boxes, which allow user to define different search criteria. In case user selects nothing in a combo box, it does mean that user want to select all data in this criterion (in other words, omit the filter)

The idea is simple, but when I implement it in Linq, it painful. I don't know how to optionally add criteria into the query. Here is my "concept" query, which, of course, does not work:

var context = new Entities();
        var complaints = from c in context.Complaints
                         join s in context.Statuses on c.Status equals s.Id
                         join service in context.SERVICES on c.ServiceId equals service.Id
                         join u in context.Users on c.CreatedBy equals u.UserId
                         from technician in context.Users.Where(technician => technician.UserId == c.AssignedTo).DefaultIfEmpty()
                         where c.ResellerId == CurrentUser.ResellerID
                         && c.CreatedBy == (decimal)ASPxComboBoxSupporter.Value //if Supporter is selected and so on
                         && c.AssignedTo == (decimal)ASPxComboBoxTechnician.Value
                         && c.ServiceId == (decimal)ddlService.Value
                         && c.Status == (decimal)ddlStatus.Value
                         select new
                         {
                             c.Id,
                             c.Status,
                             s.Name,
                             c.ServiceId,
                             Service = service.Name,
                             c.Title,
                             c.Customer,
                             c.Description,
                             c.CreatedDate,
                             c.CreatedBy,
              开发者_运维技巧               Author = u.Username,
                             c.AssignedBy,
                             c.AssignedTo,
                             Technician = technician.Username,
                             c.AssignedDate
                         };

How can I do this?


Instead of creating it using the more SQL style Linq syntax (sorry I don't know the proper name for it), you could try taking advantage of the way IQueryable objects work. Basically what you can do is add where clauses where necessary, otherwise omit them. Something along these lines should work:

var context = new Entities();
var complaints = from c in context.Complaints
                 join s in context.Statuses on c.Status equals s.Id
                 join service in context.SERVICES on c.ServiceId equals service.Id
                 join u in context.Users on c.CreatedBy equals u.UserId
                 from technician in context.Users.Where(technician => technician.UserId == c.AssignedTo).DefaultIfEmpty()
                 select new
                 {
                     c.Id,
                     c.Status,
                     s.Name,
                     c.ServiceId,
                     Service = service.Name,
                     c.Title,
                     c.Customer,
                     c.Description,
                     c.CreatedDate,
                     c.CreatedBy,
                     Author = u.Username,
                     c.AssignedBy,
                     c.AssignedTo,
                     Technician = technician.Username,
                     c.AssignedDate
                 };

So keep in mind you haven't actually queried anything yet, because Linq uses deferred execution. Now you can go through and add where clauses

if (ASPxComboBoxSupporter.Value != null)
{
    complaints = complaints.Where(c => c.CreatedBy == (decimal)ASPxComboBoxSupporter.Value);
}
if (ASPxComboBoxTechnician.Value != null)
{
    complaints = complaints.Where(c => c.AssignedTo == (decimal)ASPxComboBoxTechnician.Value);
}

if (ddlService.Value != null)
{
    complaints = complaints.Where(c => c.ServiceId == (decimal)ddlService.Value);
}

if (ddlStatus.Value != null)
{
    complaints = complaints.Where(c => c.Status == (decimal)ddlStatus.Value);
}

I haven't tested this, so let me know if something isn't working right still.


First, you have to parse the text input from the user to see if it's really a number or not, and if yes, convert it to the decimal type. There is a handy method decimal.TryParse for that:

    decimal supporter;
    bool supportedSpecified = decimal.TryParse( ASPxComboBoxSupporter.Value, out supporter );

And then you can use this information in the query:

    where c.ResellerId == CurrentUser.ResellerID
    && ( !supporterSpecified || c.CreatedBy == supporter )
    ...

Repeat for other criteria.


Take a look at the PredicateBuilder class described in the C# in a Nutshell book(s). It allows you to dynamically build a predicate to use with LINQ to SQL and Entity Framework.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜