LINQ to SQL querying same column multiple times

dynamic-linq linq linq-to-sql

Question

I have a bunch of parameters that I pass into a C# method that uses LINQ to SQL. All of these parameters are filters from a UI. Four of the parameters I need to filter are in the same column in the same table. For example, the table may look like:

ID | FK_ID | Name | Value

1 1 Param1 p1Val
2 1 Param2 p2Val
3 1 Param3 p3.Val
3 1 Param4 p4.Val

I need to take the filter parameters and match them up to the Value column and also ensure that the Name is correct. Currently, I do this by joining the same table multiple times...but I fear that is far too inefficient. What's the best way to do this? I think I'd like to build the query dynamically so I can check which filters are set but I'm struggling with how I should build my result set. Right now, it looks like: (FYI ContextProperties is the table in question)

var result = 

from f in dataContext.Faults
join m in dataContext.Messages on f.FaultID equals m.FaultID              
join c in dataContext.ContextProperties on m.MessageID equals c.MessageID
join cp in dataContext.ContextProperties on c.MessageID equals cp.MessageID
join cpp in dataContext.ContextProperties on cp.MessageID equals cpp.MessageID
join cppp in dataContext.ContextProperties on cpp.MessageID equals cppp.MessageID
where (f.DateTime >= initDate && f.DateTime <= finishDate) &&
                     f.FaultID == (faultID != Guid.Empty ? faultID : f.FaultID) &&
                     f.Application == (!string.IsNullOrEmpty(application) ? application : f.Application) &&
                     f.FaultCode == (!string.IsNullOrEmpty(faultCode) ? faultCode : f.FaultCode) &&
                     f.FailureCategory == (!string.IsNullOrEmpty(failureCategory) ? failureCategory : f.FailureCategory) &&
                     f.ErrorType == (!string.IsNullOrEmpty(errorType) ? errorType : f.ErrorType) &&
                     (f.FaultSeverity >= 0 && f.FaultSeverity <= maxFaultSeverity)
                     where (c.Value.ToString() == (!string.IsNullOrEmpty(geniusReference) ? geniusReference : c.Value.ToString())
                        && c.Name.ToString() == "GeniusReference") 
                     where (cp.Value.ToString() == (!string.IsNullOrEmpty(programNumber) ? programNumber : cp.Value.ToString())
                        && cp.Name.ToString() == "ProgramGeniusNumber")
                     where (cpp.Value.ToString() == (!string.IsNullOrEmpty(platform) ? platform : cpp.Value.ToString())
                        && cpp.Name.ToString() == "Platform")
                     where (cppp.Value.ToString() == (!string.IsNullOrEmpty(modifiedBy) ? modifiedBy : cppp.Value.ToString())
                        && cppp.Name.ToString() == "ModifiedBy")
                     select new FaultsWithFilters {
                                                    DateTime = f.DateTime
                                                    ,FaultID = f.FaultID
                                                    ,Scope = f.Scope
                                                    ,FaultCode = f.FaultCode
                                                    ,FaultSeverity = f.FaultSeverity
                                                    ,ErrorType = f.ErrorType
                                                    ,Description = f.Description
                                                    ,FaultDescription = f.FaultDescription
                                                    ,FailureCategory = f.FailureCategory
                                                    ,GeniusReference = c.Value.ToString()
                                                    ,ProgramNumber = cp.Value.ToString()
                                                    ,Platform = cpp.Value.ToString()
                                                    ,ModifiedBy = cppp.Value.ToString()
                                                    };

followed by a bunch of where statements and the select. Thanks in advance for the help! PS sorry for crappy formatting.

1
0
4/12/2013 2:57:17 PM

Accepted Answer

Create your query one clause at the time instead of really bad-looking field == (filterSet ? filter : field).

First join all necessary tables:

var query = dataContext.Faults.Join(dataContext.Messages, f => f.FaultID, m => mFaultID, new { f, m })
                              .Join(dataContext.ContextProperties, x => x.m.MessageID, c => c.MessageID, new { x.f, x.m, c });
                              // add all other joins here
                              // and all where conditions that are always valid

Then add conditional where conditions:

if(!string.IsNullOrEmpty(geniusReference))
{
    query = query.Where(x => x.c.Value.ToString() == geniusReference);
}

// instead of:
// where (c.Value.ToString() == (!string.IsNullOrEmpty(geniusReference) ? geniusReference : c.Value.ToString())

At the end add projection:

var results = from x in query
              select new FaultsWithFilters {
                   DateTime = x.f.DateTime
                  ,FaultID = x.f.FaultID
                  ,Scope = x.f.Scope
                  ,FaultCode = x.f.FaultCode
                  ,FaultSeverity = x.f.FaultSeverity
                  ,ErrorType = x.f.ErrorType
                  ,Description = x.f.Description
                  ,FaultDescription = x.f.FaultDescription
                  ,FailureCategory = x.f.FailureCategory
                  ,GeniusReference = x.c.Value.ToString()
                  ,ProgramNumber = x.cp.Value.ToString()
                  ,Platform = x.cpp.Value.ToString()
                  ,ModifiedBy = x.cppp.Value.ToString()
              };
0
4/12/2013 3:07:05 PM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow