linq in silverlight with C# - c#

I cache some tables
and use where and Any with LINQ
Result = Result.Where(r => smsRoleFunctional.Any((b => b == r.Field<Guid?>("Functional_PCode")))).ToList();
performance is ok but when I add or condition
Result = Result.Where(r => smsRoleFunctional.Any((b => b == r.Field<Guid?>("Functional_PCode") || r.Field<Guid?>("Functional_PCode") == null))).ToList();
performance is not ok
how to write this query with or condition that perfomance become better

Related

Add a if statement condition to a Linq statement

I am wanting a nice clean approach to adding in a conditional to an existing linq statement . I have a NEW variable personContactRoleId which will be zero or not zero.
context.PersonContactRoles
.Where(pcr => pcr.PersonId == personId);
.ToList()
.ForEach(pcr =>
{
// a lot of code
}
I was able to solve it with the iqueryable deferment of execution using an if statement, but it seems rather ugly and possibly less performant? Anything better to use?
var query = context.PersonContactRoles
.Where(pcr => pcr.PersonId == personId);
if(personContactRoleId != 0)
{
query = query.Where(b => b.PersonContactRoleId == personContactRoleId);
}
var results = query.ToList();
results.ForEach(pcr =>
{
// a lot of code
}
Again, this works, but looking for a cleaner way of doing this
The solution you have is fine, but if you want to put it all into one query without an if, you can add an additional Where condition that returns records where either personContactRoleId == 0 or prc.PersonContactRoleId == personContactRoleId is true:
context.PersonContactRoles
.Where(pcr =>
pcr.PersonId == personId &&
(personContactRoleId == 0 || pcr.PersonContactRoleId == personContactRoleId))
.ToList()
.ForEach(pcr =>
{
// a lot of code
});
This works without a need for an if block that checks that personContactRoleId is not 0
var query = context.PersonContactRoles
.Where(pcr => pcr.PersonId == personId).Where(b => {
return b.PersonContactRoleId == personContactRoleId && personContactRoleId != 0
}).ToList().ForEach(pcr =>
{
// a lot of code
}

How to make LINQ query with Unions more efficient

I inherited the LINQ query below and I feel that the query can be refactored for efficiency. The query currently takes about 6-8 seconds of processing time to return one record to the user on the front-end of the application. LINQ is not my strong suite, so any help would be greatly appreciated.
The query should ultimately produce a distinct list of CA_TASK_VW objects that are tied to a list of distinct CA_OBJECT_ID's obtained from the CA_OBJECT, CA_PEOPLE, and CA_CONTRACTOR tables.
var data = (from a in _db.CA_TASK_VW
where a.TASK_TYPE == "INSPECTION" && a.TASK_AVAILABLE_FLAG == "Y" && a.TARGET_END_DATE == null
select a).AsQueryable();
data = data.Join(_db.CA_OBJECT.Where(o => o.ENTERED_BY == _userId),
o => o.CA_OBJECT_ID, p => p.CA_OBJECT_ID,
(t, p) => t)
.Union(data.Join(_db.CA_PEOPLE.Where(p => p.EMAIL == _email),
t => t.CA_OBJECT_ID, p => p.CA_OBJECT_ID,
(t, p) => t))
.Union(data.Join(_db.CA_CONTRACTOR.Where(c => c.CONTRACTOR.EMAIL == _email),
t => t.CA_OBJECT_ID, c => c.CA_OBJECT_ID,
(t, c) => t));
The code seems to be using Join/Union to execute basically a where predicate on the list of CA_TASK_VW, filtering it step by step to the final result, so what happens if you just specify the where condition directly?
var data = from a in _db.CA_TASK_VW
where a.TASK_TYPE == "INSPECTION" && a.TASK_AVAILABLE_FLAG == "Y" && a.TARGET_END_DATE == null
select a;
data = data.Where(t => _db.CA_OBJECT.Where(o => o.ENTERED_BY == _userId).Select(o => o.CA_OBJECT_ID).Contains(t.CA_OBJECT_ID) ||
_db.CA_PEOPLE.Where(p => p.EMAIL == _email).Select(p => p.CA_OBJECT_ID).Contains(t.CA_OBJECT_ID) ||
_db.CA_CONTRACTOR.Where(c => c.CONTRACTOR.EMAIL == _email).Select(c => c.CA_OBJECT_ID).Contains(t.CA_OBJECT_ID));
You could try using UNION ALL if you don`t really care about duplicates in your query results as it works much faster than UNION

Using two Linq query in a single method

As shown in the below code, the API will hit the database two times to perform two Linq Query. Can't I perform the action which I shown below by hitting the database only once?
var IsMailIdAlreadyExist = _Context.UserProfile.Any(e => e.Email == myModelUserProfile.Email);
var IsUserNameAlreadyExist = _Context.UserProfile.Any(x => x.Username == myModelUserProfile.Username);
In order to make one request to database you could first filter for only relevant values and then check again for specific values in the query result:
var selection = _Context.UserProfile
.Where(e => e.Email == myModelUserProfile.Email || e.Username == myModelUserProfile.Username)
.ToList();
var IsMailIdAlreadyExist = selection.Any(x => x.Email == myModelUserProfile.Email);
var IsUserNameAlreadyExist = selection.Any(x => x.Username == myModelUserProfile.Username);
The .ToList() call here will execute the query on database once and return relevant values
Start with
var matches = _Context
.UserProfile
.Where(e => e.Email == myModelUserProfile.Email)
.Select(e => false)
.Take(1)
.Concat(
_Context
.UserProfile
.Where(x => x.Username == myModelUserProfile.Username)
.Select(e => true)
.Take(1)
).ToList();
This gets enough information to distinguish between the four possibilities (no match, email match, username match, both match) with a single query that doesn't return more than two rows at most, and doesn't retrieve unused information. Hence about as small as such a query can be.
With this done:
bool isMailIdAlreadyExist = matches.Any(m => !m);
bool isUserNameAlreadyExist = matches.LastOrDefault();
It's possible with a little hack, which is grouping by a constant:
var presenceData = _Context.UserProfile.GroupBy(x => 0)
.Select(g => new
{
IsMailIdAlreadyExist = g.Any(x => x.Email == myModelUserProfile.Email),
IsUserNameAlreadyExist = g.Any(x => x.Username == myModelUserProfile.Username),
}).First();
The grouping gives you access to 1 group containing all UserProfiles that you can access as often as you want in one query.
Not that I would recommend it just like that. The code is not self-explanatory and to me it seems a premature optimization.
You can do it all in one line, using ValueTuple and LINQ's .Aggregate() method:
(IsMailIdAlreadyExist, IsUserNameAlreadyExist) = _context.UserProfile.Aggregate((Email:false, Username:false), (n, o) => (n.Email || (o.Email == myModelUserProfile.Email ? true : false), n.Username || (o.Username == myModelUserProfile.Username ? true : false)));

LINQ subquery with multiple columns

I'm trying to recreate this SQL query in LINQ:
SELECT *
FROM Policies
WHERE PolicyID IN(SELECT PolicyID
FROM PolicyRegister
WHERE PolicyRegister.StaffNumber = #CurrentUserStaffNo
AND ( PolicyRegister.IsPolicyAccepted = 0
OR PolicyRegister.IsPolicyAccepted IS NULL ))
Relationship Diagram for the two tables:
Here is my attempt so far:
var staffNumber = GetStaffNumber();
var policyRegisterIds = db.PolicyRegisters
.Where(pr => pr.StaffNumber == staffNumber && (pr.IsPolicyAccepted == false || pr.IsPolicyAccepted == null))
.Select(pr => pr.PolicyID)
.ToList();
var policies = db.Policies.Where(p => p.PolicyID.//Appears in PolicyRegisterIdsList)
I think I'm close, will probably make two lists and use Intersect() somehow but I looked at my code this morning and thought there has to be an easier way to do this,. LINQ is supposed to be a more readble database language right?
Any help provided is greatly appreciated.
Just use Contains:
var policies = db.Policies.Where(p => policyRegisterIds.Contains(p.PolicyID));
Also better store policyRegisterIds as a HashSet<T> instead of a list for search in O(1) instead of O(n) of List<T>:
var policyRegisterIds = new HashSet<IdType>(db.PolicyRegisters......);
But better still is to remove the ToList() and let it all happen as one query in database:
var policyRegisterIds = db.PolicyRegisters.Where(pr => pr.StaffNumber == staffNumber &&
(pr.IsPolicyAccepted == false || pr.IsPolicyAccepted == null));
var policies = db.Policies.Where(p => policyRegisterIds.Any(pr => pr.PolicyID == p.PolicyID));

Need to optimize LINQ code using Nhibernate

I 'm new to NHibernate & LINQ. I have a piece of code which I think can be optimized. Please help me to do so.
foreach (var geography in geographyList.OrderBy(x => x.Name))
{
var introductionDateDetail = environment.IntroductionDateInfo
.IntroductionDateDetails
.OrderByDescending(x => x.ApplicationDate)
.FirstOrDefault(x => x.Geography.Id == geography.Id &&
x.VaccineDetail.Id == vaccineDetail.Id &&
x.MasterForecastInfo.Id == masterforecast.Id &&
x.ViewInfo.Id == viewInfoDetail.ViewInfo.Id);
}
The for loop may iterate to about thousand records.And hence the LINQ statement is also executed that many times. Can we write a piece of code where we can execute the LINQ statement just once?
You can try something like this:
var geographiesId = geographyList.Select(g => g.Id);
var introductionDetails = environment.IntroductionDateInfo
.IntroductionDateDetails
.OrderByDescending(x => x.ApplicationDate)
.FirstOrDefault(x => geographiesId.Contains(x.Geography.Id) &&
x.VaccineDetail.Id == vaccineDetail.Id &&
x.MasterForecastInfo.Id == masterforecast.Id &&
x.ViewInfo.Id == viewInfoDetail

Categories

Resources