'Where' clause with conditional 'Contains' - linq

The following will select persons which have the keyword contained by both FirstName and LastName
if (searchFields.Contains("FirstName"))
{
query = query.Where(p => p.FirstName.Contains(keyword));
}
if (searchFields.Contains("LastName"))
{
query= query.Where(p => p.LastName.Contains(keyword));
}
How can I change it such that it will select persons with keyword contained by either FirstName or LastName ?
In other words I am looking for an OR clause, but I don't know how to do it

bool searchFirstName = searchFields.Contains("FirstName");
bool searchLastName = searchFields.Contains("LastName");
if (searchFirstName && searchLastName)
{
query = query.Where(p => p.FirstName.Contains(keyword)
|| p.LastName.Contains(keyword));
}
else if(searchFirstName)
{
query = query.Where(p => p.FirstName.Contains(keyword));
}
else if(searchLastName)
{
query = query.Where(p => p.LastName.Contains(keyword));
}

Here's what I needed:
http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx
It is using LINQ expressions, it combines them using Expression.Or

Related

How to Sortby Multiple Colums - Linq to SQL

Wanting to sortby x.IRNumber - .thenby x.BedLocation but no luck could someone help me in the right direction?
Thanks
Mark
string jobID = ddlJobID.SelectedValue;
using (rw_forms context = new rw_forms())
{
var result = from c in context.hospedia_running_sheet_view.Select(x => new
{
x.uniqueID,
x.irNumber,
x.ward,
x.bed_location,
x.bed_extension,
x.select_technology,
x.select_fitting_of_pattress,
x.select_fitting_of_backplate,
x.fixing_method_used,
x.id,
x.status,
x.latitude,
x.longitude,
x.accuracy,
x.createdAt,
x.createdByName,
x.fixing,
x.statusID,
x.commissioningID,
x.jobID,
x.siteName
}).Where(x=> x.statusID == 1).Where(x => x.jobID == ((jobID == "-1") ? x.jobID : jobID)).OrderByDescending(x => x.irNumber) select c;
grdForms.DataSource = result.ToList();
grdForms.DataBind();
}
}
catch(Exception ex)
{
Response.Write(ex.ToString());
}
}
If you want something like this
SELECT * FROM TEST
ORDER BY TEST.ID,TEST.RID DESC
-
from t in db.TEST
orderby t.ID, t.RID descending
select t

Select only a single column in LINQ

The EntityModel is defined as:
Personnel has a link to a Country
When executing this code in LinqPad, I see that the SQL which is generated is not optimized (all fields are returned) in the first query ? What am I missing here or doing wrong ?
Query 1 LINQ
var Country = Countries.FirstOrDefault(o => o.Id == 100000581);
var personnelIds = Country.Personnels.Select(p => p.Id).ToArray();
personnelIds.Dump();
Query 1 SQL
exec sp_executesql N'SELECT [t0].[Id], [t0].[Version], [t0].[Identifier], [t0].[Name], , [t0].[UpdatedBy] FROM [Personnel] AS [t0] WHERE [t0].[Country_Id] = #p0',N'#p0 bigint',#p0=100000581
Query 2 LINQ
var Country = Countries.FirstOrDefault(o => o.Id == 100000581);
var personnelIds2 = Personnels.Where(p => p.Country == Country).Select(p => p.Id).ToArray();
personnelIds2.Dump();
Query 2 SQL
exec sp_executesql N'SELECT [t0].[Id] FROM [Personnel] AS [t0] WHERE [t0].[Country_Id] = #p0',N'#p0 bigint',#p0=100000581
The database used is SQL Express 2008. And LinqPad version is 4.43.06
//var Country = Countries.FirstOrDefault(o => o.Id == 100000581);
var personnelIds = context.Personnels
.Where(p => p.Country.Id == 100000581)
.Select(p => p.Id)
.ToArray();
personnelIds.Dump();
Try this, it should be better.
Personnels collection will be populated via lazy loading when accessed, hence retrieving all of the fields from the DB. Here's what's happening...
// retrieves data and builds the single Country entity (if not null result)
var Country = Countries.FirstOrDefault(o => o.Id == 100000581);
// Country.Personnels accessor will lazy load and construct all Personnel entity objects related to this country entity object
// hence loading all of the fields
var personnelIds = Country.Personnels.Select(p => p.Id).ToArray();
You want something more like this:
// build base query projecting desired data
var personnelIdsQuery = dbContext.Countries
.Where( c => c.Id == 100000581 )
.Select( c => new
{
CountryId = c.Id,
PersonnelIds = c.Personnels.Select( p => p.Id )
}
// now do enumeration
// your example shows FirstOrDefault without OrderBy
// either use SingleOrDefault or specify an OrderBy prior to using FirstOrDefaul
var result = personnelIdsQuery.OrderBy( item => item.CountryId ).FirstOrDefault();
OR:
var result = personnelIdsQuery.SingleOrDefault();
Then get the array of IDs if not null
if( null != result )
{
var personnelIds = result.PersonnelIds;
}
Try can also try grouping personnel into a single query
var groups =
(from p in Personnel
group p by p.CountryId into g
select new
{
CountryId = g.Key
PersonnelIds = p.Select(x => x.Id)
});
var personnelIds = groups.FirstOrDefault(g => g.Key == 100000581);
Do you have the ForeignKey explicitly defined in your POCO for Personnel? It's common to leave it out in EF, but adding it would massively simplify both this code and the resulting SQL:
public class Personnel
{
public Country Country { get; set; }
[ForeignKey("Country")]
public int CountryId { get; set; }
. . .
}
> update-database -f -verbose
var ids = db.Personnel.Where(p => p.CountryId == 100000581).Select(p => p.Id).ToArray();

Co-related Queries using lambda expressions

How can I convert this LINQ query from query syntax to method syntax? I am performing a co-related query operation.
var query = (from r in objEntities.Employee
where r.Location == (from q in objEntities.Department
where q.Location == r.Location
select q.Location).FirstOrDefault()
select new
{
FirstName = r.FirstName,
LastName = r.LastName,
Age = r.Age,
Location = r.Location
});
GridView1.DataSource = query;
GridView1.DataBind();
I think you are trying to convert the query to method-based query instead of syntax-based query.
var query = objEntities.Employee
.Where(e => e.Location == objEntities.Department
.Where(d => d.Location == r.Location)
.Select(d => d.Location)
.FirstOrDefault())
.Select(e => new {
FirstName = e.FirstName,
LastName = e.LastName,
Age = e.Age,
Location = e.Location
});
I'm also pretty sure your inner expression within where clause could be replaced with something like that:
.Where(e => objEntities.Department.Any(d => d.Location == e.Location)
Nested queries always have performance issue instead you should use join:
In the lambda expression query should be
var query = objEntities.Employee.Join(objEntities.Department, E => E.Location,
D => D.Location,
(E,D) => new {
FirstName = E.FirstName,
LastName = E.LastName,
Age = E.Age,
Location = E.Location
});

LINQ: Group By + Where in clause

I'm trying to implement a T-SQL equivalent of a where in (select ...) code in LINQ.
This is what I have now:
int contactID = GetContactID();
IEnumerable<string> threadList = (from s in pdc.Messages
where s.ContactID == contactID
group 1 by new { s.ThreadID } into d
select new { ThreadID = d.Key.ThreadID}).ToList<string>();
var result = from s in pdc.Messages
where threadList.Contains(s.ThreadID)
group new { s } by new { s.ThreadID } into d
let maxMsgID = d.Where(x => x.s.ContactID != contactID).Max(x => x.s.MessageID)
select new {
LastMessage = d.Where(x => x.s.MessageID == maxMsgID).SingleOrDefault().s
};
However, my code won't compile due to this error for the ToList():
cannot convert from
'System.Linq.IQueryable<AnonymousType#1>'
to
'System.Collections.Generic.IEnumerable<string>'
Anyone have any suggestions on how to implement this? Or any suggestions on how to simplify this code?
Your query returns a set of anonymous types; you cannot implicitly convert it to a List<string>.
Instead, you should select the string itself. You don't need any anonymous types.
Change it to
var threadList = pdc.Messages.Where(s => s.ContactID == contactID)
.Select(s => s.ThreadID)
.Distinct()
.ToList();
var result = from s in pdc.Messages
where threadList.Contains(s.ThreadID)
group s by s.ThreadID into d
let maxMsgID = d.Where(x => x.ContactID != contactID).Max(x => x.MessageID)
select new {
LastMessage = d.Where(x => x.MessageID == maxMsgID).SingleOrDefault()
};

Linq: Nested queries are better than joins, but what if you use 2 nested queries?

In her book Entity Framework Julie Lerman recommends using nested queries in preference to joins (scroll back a couple of pages).
In her example see populates 1 field this way, but what id you want to populate 2?
I have an example here where I would prefer to populate the Forename and Surname with the same nested query rather than 2 separate ones. I just need to know the correct syntax to do this.
public static List<RequestInfo> GetRequests(int _employeeId)
{
using (SHPContainerEntities db = new SHPContainerEntities())
{
return db.AnnualLeaveBookeds
.Where(x => x.NextApproverId == _employeeId ||
(x.ApproverId == _employeeId && x.ApprovalDate.HasValue == false))
.Select(y => new RequestInfo
{
AnnualLeaveDate = y.AnnualLeaveDate,
Forename = (
from e in db.Employees
where e.EmployeeId == y.EmployeeId
select e.Forename).FirstOrDefault(),
Surname = (
from e in db.Employees
where e.EmployeeId == y.EmployeeId
select e.Surname).FirstOrDefault(),
RequestDate = y.RequestDate,
CancelRequestDate = y.CancelRequestDate,
ApproveFlag = false,
RejectFlag = false,
Reason = string.Empty
})
.OrderBy(x => x.AnnualLeaveDate)
.ToList();
}
}
There's nothing wrong with your query, but you can write it in a way that is much simpler, without the nested queries:
public static List<RequestInfo> GetRequests(int employeeId)
{
using (SHPContainerEntities db = new SHPContainerEntities())
{
return (
from x in db.AnnualLeaveBookeds
where x.NextApproverId == employeeId ||
(x.ApproverId == employeeId && x.ApprovalDate == null)
orderby x.AnnualLeaveDate
select new RequestInfo
{
AnnualLeaveDate = x.AnnualLeaveDate,
Forename = x.Employee.Forename,
Surname = x.Employee.Surname,
RequestDate = x.RequestDate,
CancelRequestDate = x.CancelRequestDate,
ApproveFlag = false,
RejectFlag = false,
Reason = string.Empty
}).ToList();
}
}
See how I just removed your from e in db.Employees where ... select e.Forename) and simply replaced it with x.Employee.Forename. When your database contains the correct foreign key relationships, the EF designer will successfully generate a model that contain an Employee property on the AnnualLeaveBooked entity. Writing the query like this makes it much more readable.
I hope this helps.
try this
using (SHPContainerEntities db = new SHPContainerEntities())
{
return db.AnnualLeaveBookeds
.Where(x => x.NextApproverId == _employeeId ||
(x.ApproverId == _employeeId && x.ApprovalDate.HasValue == false))
.Select(y =>
{
var emp = db.Emplyees.Where(e => e.EmployeeId == y.EmployeeId);
return new RequestInfo
{
AnnualLeaveDate = y.AnnualLeaveDate,
Forename = emp.Forename,
Surname = emp.Surname,
RequestDate = y.RequestDate,
CancelRequestDate = y.CancelRequestDate,
ApproveFlag = false,
RejectFlag = false,
Reason = string.Empty
};
).OrderBy(x => x.AnnualLeaveDate).ToList();
}

Resources