I’ve been scouring the internet and every example I’ve found so far uses the same sort of a query to perform a search. I find this the hello world version of a search. I’ve found a few that use an if statement to select between a few queries, but still lack any real power.
(from c in context.table
where c.contains(searchField)).toList());
The search is so simple that I can not come up with how I would develop a search query for the below screenshot. Checkbox groups should create OR/IN clauses and pretty much everything else is an AND
for instance, the users checks Sarasota, Venice enters a yearbuilt 1990 and selects bedrooms 1+ and enters a sale date range from 1/1/2000 and leaves the to fieldblank.
in plain old SQL this would be.
where city = 'sarasota' or city = 'Venice' AND yearbuilt = 1990 AND bedrooms >= 1 AND fromSaleDate >= 1/1/2000 AND toSaleDate = 12/31/9999
if I was using old school sql strings and ASP classic I would use a combination of hardcoded clauses and few ifs and for statements to dynamically build the query string myself.
I’m envisioning a searchViewModel (yet to be written) of somekind that passes the values in somehow. So I can’t include a code sample of that ViewModel. And the real kicker is the Property Features section. That will be a dynamic list of available property features, so hardcoding that as part of the query is not an option.
I think somehow this might be relevant but I’m not sure. filtering a list using LINQ
Please help me take a step in the right direction. Thanks

Update
Here is the query as executed in Profiler. I tweaked it to declare the variables so I could run it interactively, but the query itself is unaltered
declare @p__linq__0 as datetime
declare @p__linq__1 as datetime
set @p__linq__0='1989-01-01 00:00:00'
set @p__linq__1='1990-01-01 00:00:00'
SELECT TOP (10)
[Project3].[STRAP] AS [STRAP],
[Project3].[SITUS] AS [SITUS],
[Project3].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Project3].[PROPERTY_USE] AS [PROPERTY_USE],
[Project3].[SUBDIVISION] AS [SUBDIVISION],
[Project3].[DSCR] AS [DSCR],
[Project3].[LAND_AREA] AS [LAND_AREA],
[Project3].[INCORPORATION] AS [INCORPORATION],
[Project3].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Project3].[CENSUS] AS [CENSUS]
FROM ( SELECT [Project3].[STRAP] AS [STRAP], [Project3].[SITUS] AS [SITUS], [Project3].[MAILING_ADDRESS] AS [MAILING_ADDRESS], [Project3].[PROPERTY_USE] AS [PROPERTY_USE], [Project3].[SUBDIVISION] AS [SUBDIVISION], [Project3].[DSCR] AS [DSCR], [Project3].[LAND_AREA] AS [LAND_AREA], [Project3].[INCORPORATION] AS [INCORPORATION], [Project3].[SEC_TWP_RGE] AS [SEC_TWP_RGE], [Project3].[CENSUS] AS [CENSUS], row_number() OVER (ORDER BY [Project3].[STRAP] ASC) AS [row_number]
FROM ( SELECT
[Distinct2].[STRAP] AS [STRAP],
[Distinct2].[SITUS] AS [SITUS],
[Distinct2].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Distinct2].[PROPERTY_USE] AS [PROPERTY_USE],
[Distinct2].[SUBDIVISION] AS [SUBDIVISION],
[Distinct2].[DSCR] AS [DSCR],
[Distinct2].[LAND_AREA] AS [LAND_AREA],
[Distinct2].[INCORPORATION] AS [INCORPORATION],
[Distinct2].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Distinct2].[CENSUS] AS [CENSUS]
FROM ( SELECT DISTINCT
[Distinct1].[STRAP] AS [STRAP],
[Distinct1].[SITUS] AS [SITUS],
[Distinct1].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Distinct1].[PROPERTY_USE] AS [PROPERTY_USE],
[Distinct1].[SUBDIVISION] AS [SUBDIVISION],
[Distinct1].[DSCR] AS [DSCR],
[Distinct1].[LAND_AREA] AS [LAND_AREA],
[Distinct1].[INCORPORATION] AS [INCORPORATION],
[Distinct1].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Distinct1].[CENSUS] AS [CENSUS]
FROM (SELECT DISTINCT
[Extent1].[STRAP] AS [STRAP],
[Extent1].[SITUS] AS [SITUS],
[Extent1].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Extent1].[PROPERTY_USE] AS [PROPERTY_USE],
[Extent1].[SUBDIVISION] AS [SUBDIVISION],
[Extent1].[DSCR] AS [DSCR],
[Extent1].[LAND_AREA] AS [LAND_AREA],
[Extent1].[INCORPORATION] AS [INCORPORATION],
[Extent1].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Extent1].[CENSUS] AS [CENSUS]
FROM [dbo].[Properties] AS [Extent1]
INNER JOIN [dbo].[Transfers] AS [Extent2] ON [Extent1].[STRAP] = [Extent2].[STRAP]
WHERE CAST( [Extent2].[TRANS_DATE] AS datetime2) >= @p__linq__0 ) AS [Distinct1]
INNER JOIN [dbo].[Transfers] AS [Extent3] ON [Distinct1].[STRAP] = [Extent3].[STRAP]
WHERE CAST( [Extent3].[TRANS_DATE] AS datetime2) <= @p__linq__1
) AS [Distinct2]
) AS [Project3]
) AS [Project3]
WHERE [Project3].[row_number] > 0
Update
if (Model == null)
{
Model = new SearchViewModel();
}
TryUpdateModel(Model);
Model.Locations = _service.GetLocations().Select(x => new SelectListItem { Text = x.Value, Value = x.Key }).ToList();
var results = _service.GetProperties();
if (Model.SelectedLocation != null)
results = (from r in results
where r.SITUS.ToLower().Contains(Model.SelectedLocation.ToLower())
select r);
if (Model.ParcelID != null)
results = (from r in results
where r.STRAP.StartsWith(Model.ParcelID.Replace("-", "")) || r.STRAP.Equals(Model.ParcelID.Replace("-", ""))
select r);
if (Model.SqftFrom != null)
results = (from r in results
from b in r.Buildings
where b.GROSS_AREA >= Model.SqftFrom
select r).Distinct();
if (Model.SqftTo != null)
results = (from r in results
from b in r.Buildings
where b.GROSS_AREA <= Model.SqftTo
select r).Distinct();
if (Model.Bedrooms != null)
results = (from r in results
from b in r.Buildings
from s in b.StructuralElements
where s.VALUE == Model.Bedrooms && s.DSCR.ToLower() == "bedrooms"
select r).Distinct();
if (Model.Bathrooms != null)
results = (from r in results
from b in r.Buildings
from s in b.StructuralElements
where s.VALUE == Model.Bathrooms && s.CATEGORY == "BT"
select r).Distinct();
if (Model.SaleAmountFrom != null)
results = (from r in results
from t in r.Transfers
where t.AMOUNT >= Model.SaleAmountFrom
select r).Distinct();
if (Model.SaleAmountTo != null)
results = (from r in results
from t in r.Transfers
where t.AMOUNT <= Model.SaleAmountTo
select r).Distinct();
if (Model.SalesFrom != null)
results = (from r in results
from t in r.Transfers
where t.TRANS_DATE >= Model.SalesFrom
select r).Distinct();
if (Model.SalesTo != null)
results = (from r in results
from t in r.Transfers
where t.TRANS_DATE <= Model.SalesTo
select r).Distinct();
//if (Model.SalesTo != null)
// results = (from r in results
// from t in r.Transfers
// where t.TRANS_DATE <= Model.SalesTo
// select r).Distinct();
results = results.OrderBy(x => x.STRAP);
Model.SearchResults = results.ToPagedList(page ??1 , size ?? 10);
if (Model.SearchResults.Count() == 1)
{
var strap = Model.SearchResults.FirstOrDefault().STRAP;
return RedirectToRoute("Details", new { id = strap });
}
else
{
return View(Model);
}
LINQ sources (
IQueryable<T>) are composable, so you can do:then finally you can do:
or:
And the trick is: it only executes the fully composed query – i.e. anything that either enumerates the query (
foreach,ToList, etc), or aggregates the query (Count,Sum, etc)