EF Order query by matched filter - entity-framework

I want to find the way to achieve order prioritization by matched field.
For example:
var query = ctx.Set<Article>()
.Where(e => e.Title == "search query" || e.Content == "search query")
.OrderBy(???)
.Take(4);
Is it possible to order the result in such a way that records matched by Title
was on top, and entries matched by Content was on bottom. In single query which requests only 4 records from database?
like this
Title Content
------------------------------
search query other text
search query other text
other text search query
other text search query

Sure it is possible. You just order by conditional expression yielding "priority" based on your match conditions. You need to replicate all except the last condition there though. Something like (pseudo code):
.Where(e => cond1(e) || cond2(e) || ... cond{N-1}(e) || condN(e))
.OrderBy(e => cond1(e) ? 0 : cond2(e) ? 1 : ... cond{N-1}(e) ? N - 1 : N)
With your sample:
string match = "search query";
var query = ctx.Set<Article>()
.Where(e => e.Title == match || e.Content == match)
.OrderBy(e => e.Title == match ? 0 : 1) // first by priority
.ThenBy(e => ...) // then by others if needed
.Take(4);

You can also combine multiple OrderBy at once like this:
string searchQuery = "search query";
int wantedResults = 4:
var query = ctx.Set<Article>()
.Where(e => e.Title.Equals(searchQuery) || e.Content.Equals(searchQuery))
.OrderBy(e => new { e.Title, e.Content })
.Take(wantedResults);

Related

Optional compare in query

Hi i have a problem with my query because i want select that items which brands are called in string subcategory. But if that subcategory is equal "none" i would to select them all i want to do it in query not in linq. Here's my function
string subcategory = HttpContext.Current.Session["subcategory"].ToString() == "none" ? "" : HttpContext.Current.Session["subcategory"].ToString();
List<int> processors = (from x in context.Processors
where (x.Price >= filters.PriceMin && x.Price <= filters.PriceMax)
where x.Brand == subcategory
select x.Product_ID).ToList();
The pattern for this in LINQ and EF is to build up the query differently for the two cases before the query is executed by calling IQueryable.ToList(); eg:
string subcategory = ...;
var q = from x in context.Processors
where (x.Price >= filters.PriceMin && x.Price <= filters.PriceMax)
select x;
if (subcategory != "none")
{
q=q.Where(x => x.Brand == subcategory);
}
var processors = q.Select(x => x.Product_ID).ToList();

EF Conditional Query to match with whatever information available doesn't work

I am trying to write a query to search employees by whatever of the 3 attributes are available in my object using Linq to Entity.
My object has First name, Last name, and Date of Birth.
My query looks like this (search is the object containing partial or full info)
var results = ctx
.emp
.Where(p =>
p.Fname == (search.Firstname ?? p.Fname)
&& p.Lname == (search.Lastname ?? p.Lname)
&& p.Dob == (search.Dob ?? p.Dob ))
The issue is that above query is matching employees with null values in each of those 3 columns along with the matching value. For instance if I provide search.Firstname to be John, it matches everyone with first name John AND everyone with null in first name.
How do I not match nulls in fields where a value is provided?
Haven't tested, but won't something like this work.
var results = ctx
.emp
.Where(p => (search.Firstname == null ? p.Fname == p.Fname : p.Fname == search.Firstname) ||
(search.Lastname == null ? p.Lname == p.Lname : p.Lname == search.Lastname) ||
(search.Dob == null ? p.Dob == p.Dob : p.Dob == search.Dob))
Please excuse the formatting. Using my mobile :)

Conditional WHERE clause on an Entity Framework context

objRecord = await _context.Persons
.Where(tbl => tbl.DeletedFlag == false)
.ToListAsync();
This is the EF code I've got which successfully gets all the records from the Person table where DeletedFlag is false.
I want to add another where criteria that if a surname has been passed in, then add the extra where clause
.Where(tbl => tbl.Surname.Contains(theSurname))
I've tried IQueryable and some other options but can't figure out how to do the equivalent of
string theSurname = "";
objRecord = await _context.Persons
.Where(tbl => tbl.DeletedFlag == false)
if ( theSurname != "") {
.Where(tbl => tbl.Surname.Contains(theSurname))
}
.ToListAsync();
which obviously doesn't work as you can't put an if statement in an EF call.
I can add a criteria afterwards that limits objRecord, but I don't want to retrieve all the records, then cut it down, I'd rather only get the records I need.
You can combine conditions in the Where method by just adding tbl.Surname.Contains(theSurname) so your final query will look like below:
objRecord = await _context.Persons
.Where(tbl => tbl.DeletedFlag == false &&
tbl.Surname.Contains(theSurname))
.ToListAsync();
You have to apply logical AND (&&) with the existing condition in Where clause i.e. tbl.Surname.Contains(theSurname);
So your query would be
.Where(tbl => tbl.DeletedFlag == false && tbl.Surname.Contains(theSurname));

Query whether string field contains digit in Entity Framework

How do I query for all entities where a string column contains a digit in Entity Framework?
e.g.
"100 Main Street" // match
"Will advise" // no match
I really don't want to do this:
myclass.Property.Contains("0")
|| myclass.Property.Contains("1")
|| myclass.Property.Contains("2")
|| myclass.Property.Contains("3")
|| myclass.Property.Contains("4")
|| myclass.Property.Contains("5")
|| myclass.Property.Contains("6")
|| myclass.Property.Contains("7")
|| myclass.Property.Contains("8")
|| myclass.Property.Contains("9")
You could try using Contains method on array of digits:
var digits = Enumerable.Range(0, 10).Select(s=>s.ToString()).ToArray();
var result = YOURCONTEXT.YOUR_TABLE
.Where(n => digits.Any(d =>
n.YOUR_FIELD.Contains(d)))
.ToList();
You can use SqlFunctions.PatIndex to check if the column contains a digit:
where SqlFunctions.PatIndex("%[0-9]%", myClass.Property) != 0

Linq to entities where condition not working

var records = (from m in ctx.myData
from StatusReport in ctx.ReportStatusDetails
where (m.UserId == user.UserId &&
StatusReport.StatusId == 1 &&
ctx.Report.Any(r => r.ReportDate.Month == SqlFunctions.GetDate().Value.Month &&
r.ReportDate.Year == SqlFunctions.GetDate().Value.Year))
select new
{
m.Id,
m.Company.CompanyName,
m.UserId,
m.aspnet_Membership.aspnet_Users.UserName,
m.aspnet_Membership.Email
})
.Distinct()
.ToList();
The where condition StatusReport.StatusId == 1 is not working. The query is returning even rows where StatusReport.StatusId is not equal to 1.
Why is this condition being ignored?
Because you did not joined/related StatusReport with m. And result contains only m. See example http://msdn.microsoft.com/en-us/library/bb311040.aspx