I am new to LINQ queries and want to use FirstOrDefault in my existing LINQ query.
List<vUserAll> employee = (from o in db.vUsersAll
where (o.sAMAccountName == modifiedAccountName || o.CN == modifiedAccountName) && o.Domain == "dExample"
select o).ToList();
What's the correct way to do this?
This can be simplified further as:
var filtered = db.vUsersAll.FirstOrDefault(u => u. Field == filter);
If the above mentioned is the case, then you can use a labmda as in the following:
var firstOrDefaultResult = db.vUsersAll.Where(o=>
(o.sAMAccountName == modifiedAccountName || o.CN == modifiedAccountName)
&& o.Domain == "dExample").FirstOrDefault()
If you want to use the same above expression then,
vUserAll employee = (from o in db.vUsersAll
where (o.sAMAccountName == modifiedAccountName || o.CN == modifiedAccountName) && o.Domain == "dExample"
select o).FirstOrDefaul();
It's a lot easier if you only use LINQ extensions. For example,
var filtered = all users.Where(u => u. Field == filter).FirstOrDefault();
Related
I'm writing a function that builds a query based on a condition. What I want to do is have a different select statements for each condition (the query in a separate method, then each user can have his\her own select statements).
Kinda like this
var q = BuildQuery();
var nq = q.Select(...);
return nq.ToList();
Will write a query using extension method syntax solves the ' a query body must end with a select or group clause'.
Here's my query
return (from ScheduleItemAttendee SIA in context.ScheduleItemAttendees
join AttendeeService AS in context.AttendeeServices on SIA.Id equals AS.AttendeeId into x
from Att in x.DefaultIfEmpty()
where (Att == null || !Att.IsDeleted)
&& !(SIA == null || SIA.IsDeleted)
&& ((string.IsNullOrEmpty(criteria.Keyword)) || (SIA.Individual.FullNameAr.Trim().ToLower().Contains(criteria.Keyword) || SIA.Individual.FullNameEn.Trim().ToLower().Contains(criteria.Keyword))));
Try this:
public IQueryable<T> BuildQuery<T>(Expression<Func<ScheduleItemAttendee, AttendeeService, T>> selector)
{
return
from ScheduleItemAttendee SIA in context.ScheduleItemAttendees
join AttendeeService AS in context.AttendeeServices on SIA.Id equals AS.AttendeeId into x
from Att in x.DefaultIfEmpty()
where (Att == null || !Att.IsDeleted)
&& !(SIA == null || SIA.IsDeleted)
&& ((string.IsNullOrEmpty(criteria.Keyword))
|| (SIA.Individual.FullNameAr.Trim().ToLower().Contains(criteria.Keyword)
|| SIA.Individual.FullNameEn.Trim().ToLower().Contains(criteria.Keyword)))
select selector(SIA, null);
}
Then use it like this:
var q = BuildQuery((sia, att) => 42);
(Put something meaningful in the place of 42.)
I have this scenario in which i query with FindByMany (which takes the lambda and returns post if user country and category matches, (as seen in the "else")
But now i need to customize the return with prefered subcategories from users, so what im doing is query n times foreach subcategory and just addRange. I dont want to query 5 times the db if the user has 5 subcategories as favorite, but i dont know how to apply a dinamic OR.
So my question is, how can this code be improved for performance.
var posts = new List<Content>();
if (request.UserId != 0)
{
var user = _userRepository.FindBy(u => u.Id == request.UserId);
if (user != null && user.SubCategories.Any())
{
foreach (var temp in user.SubCategories.Select(subCategory => _contentRepository.FindManyBy(
c =>
c.Country.Id == country.Id && c.Category.Id == theCategory.Id &&
c.SubCategory.Id == subCategory.Id).ToList()))
{
posts.AddRange(temp);
}
}
}
else
{
posts = _contentRepository.FindManyBy(
c => c.Country.Id == country.Id && c.Category.Id == theCategory.Id
).ToList();
}
Could you not just materalise the sub-categories into a list, and then in your FindBy use a thatlist.Contains()?
You can get the user's sub-categories with one query and then use the list and the Contains method to filter the relevant posts. Contains method is supported by most LINQ query provides and should be translated into a single database query.
var subcategories = user.SubCategories.ToList();
foreach (var temp in _contentRepository.FindManyBy(
c =>
c.Country.Id == country.Id && c.Category.Id == theCategory.Id &&
subcategories.Contains( subCategory.Id ) ).ToList()))
{
posts.AddRange(temp);
}
You can build expression for where clause using Expression.OrElse or use enter link description here
The core of the problem is that you're forcing query execution for each item instead of dynamically building the query. #Milney has the right idea; example code below.
IEnumerable<int> subCategoryIds = user.SubCategories.Select(x => x.Id);
var posts = _contentRepository.FindByMany(c => c.Country.Id == country.Id
&& c.Category.Id == theCategory.Id
&& subCategoryIds.Contains(c.SubCategoryId)).ToList();
I have a ternary operator as below for a LINQ query as shown
var sub = (SubordinationType == 1) ? (true&false) : false;
var query = from vw in dbContext.vw
where (vw.office == FieldOffice && vw.SubAgreement == sub)
select vw;
Here SubAgreement is a bit field in database I need to select both true and false(0,1) or false(0) based on the ternery how do i achieve this?
Any quick suggestions please.
I think I get your question. Your logic is:
If Subordination is 1, SubAgreement doesn't matter (true or false)
If Subordination is not 1, SubAgreement should be false
hence add another condition:
//..
where (vw.office == FieldOffice && (Subordination == 1 || !vw.SubAgreement))
Try something like:
var query = from vw in dbContext.vw
where vw.office == FieldOffice
select vw;
if (SubordinationType != 1)
{
query = query.Where(vw => vw.SubAgreement == false);
}
In LINQ it's very easy to add new where clauses that are in && with the other clauses (note that it's only easy to add if you want them to be in &&, the || case is much more complex! :-) )
You can make a condition that is true when SubordinationType is 1 or when SubAgreement is false:
var query = from vw in dbContext.vw
where (vw.office == FieldOffice && (SubordinationType == 1 || vw.SubAgreement == false))
select vw;
i have the sql below that i would like to convert to C# using linq. Can someone tell me how this best can be done with linq?
select A.field1, A.Field2, A.Field4, A.Field5, A.Field4 ,A.Field6
from MPhoneParts A
where A.Field3= 'Batteri' AND NOT EXIST(
select * from MPhoneParts B where
B.Field3='cover'
A.Field2= B.Field2 AND
A.Field4= B.Field4 AND
B.Field6='Production354')
Cheers
Mike
There may be a better approach (quite possibly using a join...), but:
var query = from a in db.MPhoneParts
where a.Field3 == "Batteri" &&
!db.MPhoneParts.Any(b => b.Field3 == "cover" &&
a.Field2 == b.Field2 &&
a.Field4 == b.Field4 &&
b.Field6 == "Production354")
select a;
I assume your question is mistyped and you meant to check for the NOT IN clause.
here is the solution on how to write the NOT IN... in linq, hope this helps:
The NOT IN clause in LINQ to SQL
var qry =
from a in db.PhoneParts
where a.Field3 == "Batteri"
&& !db.PhoneParts.Any(b =>
b.Field3 == "cover"
&& b.Field6 == "Production354"
&& b.Field2 == a.Field2
&& b.Field4 == a.Field4)
select new { a.Field1, a.Field2, a.Field4, a.Field5, a.Field6 };
But thoughts:
Field1 thru Field6 are horrible names
you can use the existing SQL via db.ExecuteQuery
I have a LINQ query:
var list = from t in ctn.Items
where t.DeliverySelection == true && t.Delivery.SentForDelivery == null
orderby t.Delivery.SubmissionDate
select t;
How can I modify this query to select just five results from the database?
var list = (from t in ctn.Items
where t.DeliverySelection == true && t.Delivery.SentForDelivery == null
orderby t.Delivery.SubmissionDate
select t).Take(5);
The solution:
var list = (from t in ctn.Items
where t.DeliverySelection == true && t.Delivery.SentForDelivery == null
orderby t.Delivery.SubmissionDate
select t).Take(5);
This can also be achieved using the Lambda based approach of Linq;
var list = ctn.Items
.Where(t=> t.DeliverySelection == true && t.Delivery.SentForDelivery == null)
.OrderBy(t => t.Delivery.SubmissionDate)
.Take(5);
[Offering a somewhat more descriptive answer than the answer provided by #Ajni.]
This can also be achieved using LINQ fluent syntax:
var list = ctn.Items
.Where(t=> t.DeliverySelection == true && t.Delivery.SentForDelivery == null)
.OrderBy(t => t.Delivery.SubmissionDate)
.Take(5);
Note that each method (Where, OrderBy, Take) that appears in this LINQ statement takes a lambda expression as an argument. Also note that the documentation for Enumerable.Take begins with:
Returns a specified number of contiguous elements from the start of a
sequence.
Additional information
Sometimes it is necessary to bind a model into a view models and give a type conversion error. In this situation you should use ToList() method.
var list = (from t in ctn.Items
where t.DeliverySelection == true && t.Delivery.SentForDelivery == null
orderby t.Delivery.SubmissionDate
select t).Take(5).ToList();
Just thinking you might be feel unfamiliar of the sequence From->Where->Select, as in sql script, it is like Select->From->Where.
But you may not know that inside Sql Engine, it is also parse in the sequence of
'From->Where->Select', To validate it, you can try a simple script
select id as i from table where i=3
and it will not work, the reason is engine will parse Where before Select, so it won't know alias i in the where. To make this work, you can try
select * from (select id as i from table) as t where i = 3