LINQ how to get data using Id’s - linq

Ok I have all the carers that have clients from their local authority, but how do I get the client’s name? The client’s name is stored in the client table linked by ClientId. I would like to do it all in one query if possible.
Any pointers much appreciated.
var Records = (from x in db.Cares
where x.LocalAuthorityId == ClientLocalAuthorityId
select new {
ClientId = x.ClientId,
}).ToList();

Thanks everyone, I've worked it out
var Records = (from c in db.Cares
join x in db.Clients
on c.ClientId equals x. ClientId into eGROUP
from x in eGROUP.DefaultIfEmpty()
where x.LocalAuthorityId == ClientLocalAuthorityId
select new {
ClientName = x.ClientName,
}).ToList();

Related

Entity Framework returns wrong data after execution of two similar queries

I have two similar queries, the first one:
var activatedSerialNumbers = (from activation in entities.Activations
where !canceledActivationsIds.Contains(activation.Id)
where activation.CustomerId == customerId
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals licenseConfiguration.ActivationId
where licenseConfiguration.ProductId == productId
join activatedSerialNumber in entities.ActivatedSerialNumbers
on activation.Id equals activatedSerialNumber.ActivationId
where deactivatedSams.All(dsn => dsn.ToLower() !=
activatedSerialNumber.Name.ToLower())
select new SamWithLicense
{
Name = activatedSerialNumber.Name,
Features = licenseConfiguration.LicenseFeatures
}).ToList();
The second:
var activationsForSam = (from activation in entities.Activations
where !canceledActivationsIds.Contains(activation.Id)
where activation.CustomerId == customerId
let activatedSerialNumbers = activation.ActivatedSerialNumbers
.Select(sn => sn.Name.ToLower())
where activatedSerialNumbers.Contains(loweredSn)
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals activatedProduct.ActivationId
select new SamWithLicense
{
Name = selectedSerialNumber,
Features = licenseConfiguration.LicenseFeatures
}).ToList();
In some situations I execute them one after another and in most cases it works fine, but somethimes - not. In the result of second query Counter takes from another row:
Visual Studio - Quick watch
SQL Management Studio
I guess it's a matter of a EF cache or smth, but don't know how to fix it properly.
In your first query you are joining the Activation Id (PK) to LicenseConfigurations ActivationId (FK)
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals licenseConfiguration.ActivationId
in your second query, it looks like you are joining on a value defined outside of the query "activatedProduct"
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals activatedProduct.ActivationId

Speed up LINQ query - EF5

I have the following LINQ query using EF5 and generic repository, unit of work patterns to a SQL Server 2008 db
var countriesArr = GetIdsFromDelimStr(countries);
var competitionsArr = GetIdsFromDelimStr(competitions);
var filterTeamName = string.Empty;
if (teamName != null)
{
filterTeamName = teamName.ToUpper();
}
using (var unitOfWork = new FootballUnitOfWork(ConnFooty))
{
// give us our selection of teams
var teams =
(from team in
unitOfWork.TeamRepository.Find()
where ((string.IsNullOrEmpty(filterTeamName) || team.Name.ToUpper().Contains(filterTeamName)) &&
(countriesArr.Contains(team.Venue.Country.Id) || countriesArr.Count() == 0))
select new
{
tId = team.Id
}).Distinct();
// give us our selection of contests
var conts = (
from cont in
unitOfWork.ContestRepository.Find(
c =>
((c.ContestType == ContestType.League && competitionsArr.Count() == 0) ||
(competitionsArr.Contains(c.Competition.Id) && competitionsArr.Count() == 0)))
select new
{
contId = cont.Id
}
).Distinct();
// get selection of home teams based on contest
var homecomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
where
teams.Any(t => t.tId == fixt.HomeTeam.Id) &&
conts.Any(c => c.contId == fixt.Contest.Id)
select new
{
teamId = fixt.HomeTeam.Id,
teamName = fixt.HomeTeam.Name,
countryId = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Id : 0,
countryName = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Name : string.Empty,
compId = fixt.Contest.Competition.Id,
compDesc = fixt.Contest.Competition.Description
}).Distinct();
// get selection of away teams based on contest
var awaycomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
where
teams.Any(t => t.tId == fixt.AwayTeam.Id) &&
conts.Any(c => c.contId == fixt.Contest.Id)
select new
{
teamId = fixt.AwayTeam.Id,
teamName = fixt.AwayTeam.Name,
countryId = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Id : 0,
countryName = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Name : string.Empty,
compId = fixt.Contest.Competition.Id,
compDesc = fixt.Contest.Competition.Description
}).Distinct();
// ensure that we return the max competition based on id for home teams
var homemax = (from t in homecomps
group t by t.teamId
into grp
let maxcomp = grp.Max(g => g.compId)
from g in grp
where g.compId == maxcomp
select g).Distinct();
// ensure that we return the max competition based on id for away teams
var awaymax = (from t in awaycomps
group t by t.teamId
into grp
let maxcomp = grp.Max(g => g.compId)
from g in grp
where g.compId == maxcomp
select g).Distinct();
var filteredteams = homemax.Union(awaymax).OrderBy(t => t.teamName).AsQueryable();
As you can see we want to return the following format which is passed across to a WebAPI so we cast the results to types we can relate to in the UI.
Essentially what we are trying to do is get the home and away teams from a fixture, these fixtures have a contest which relates to a competition. We then get the highest competition id from the grouping and then this is returned with that team. The country is related to the team based on the venue id, when I was originally doing this i had problems figuring out how to do OR joins in linq which is why i split it down to getting home teams and away team and then grouping them based on competition then unioning them together.
An idea of current table size is fixtures has 7840 rows, teams has 8581 rows, contests has 337 rows and competitions has 96 rows. The table that is likely to increase rapidly is the fixture table as this is related to football.
The output we want to end up with is
Team Id, Team Name, Country Id, Country Name, Competition Id, Competition Name
Using no filtering this query takes on average around 5 secs, just wondering if anybody has any ideas/pointers on how to make it quicker.
thanks in advance Mark
I can't judge whether it will speed up things, but your homemax and awaymax queries could be
var homemax = from t in homecomps
group t by t.teamId into grp
select grp.OrderByDescending(x => x.compId).FirstOrDefault();
var awaymax = from t in awaycomps
group t by t.teamId into grp
select grp.OrderByDescending(x => x.compId).FirstOrDefault();
Further, as you are composing one very large query it may perform better when you cut it up in a few smaller queries that fetch intermediary results. Sometimes a few more roundtrips to the database perform better than one very large query for which the database engine can't find a good execution plan.
Another thing is all these Distinct()s. Do you always need them? I think you can do without because you are always fetching data from one table without joining a child collection. Removing them may save a bunch.
Yet another optimization could be to remove the ToUpper. The comparison is done by the database engine in SQL and chances are that the database has a case-insensitive collation. If so, the comparison is never case sensitive even if you'd want it to be! Constructs like Name.ToUpper cancel the use of any index on Name (it is not sargable).

Linq NOT EXISTS multiple tables

I want to do a LINQ NOT EXISTS on query MULTIPLE TABLES.
All examples on Google or SO are handling two tables I'm working with three so I'm struggling as a newbie on LINQ on how to reference them correctly.
First I tried this LINQ query
var nocertificates = (
from x in rmdb.t_certificates
from ce in rmdb.t_user_certificates
from u in rmdb.t_users
where u.id == ce.uid && ce.value != x.id
select x).AsEnumerable().Select(x => new ViewModelCheckBox()
{
Value = x.id.ToString(),
Name = x.name,
Checked = false
});
I used the ugly three times from as I'm not that good with creating types for joining.
But that gave wrong result and I realized I had to go for a NOT EXISTS
So I built a new query in T-SQL
This is the SQL query it works!
select distinct * from t_certificates tc
where NOT EXISTS
(
select distinct * from t_users tu, t_user_certificates tuc
WHERE tu.email = 'user#email.com'
and tu.id = tuc.[uid]
and tuc.value = tc.id
)
How would I do that in LINQ?
This is the question, I will award my answer for that!
BUT!
When we are at it... I'm really curious on the answer.. Is it possible to do one LINQ query that return an Ienumerable with both those that EXISTS and NOT EXISTS resulting in an object which will hold DIFFERENT VALUES on the checked property EXISTS -> CHECKED = true NOT EXISTS -> CHECKED = false
This is how I create my object.
.Select(x => new ViewModelCheckBox()
{
Value = x.id.ToString(),
Name = x.name,
Checked = this should be different based on exists or not
});
The LINQ answer should look something like this (untested):
var nocertificates =
from x in rmdb.t_certificates
join tuc in (
from u in rmdb.t_users
join ce in rmdb.t_user_certificates on u.id == ce.uid
select ce.value
) on tuc.value = tc.id into tuc
from y in tuc.DefaultIfEmpty()
where y == null
select x;
This is what I ended up using!
var query = (from tc in rmdb.t_certificates
where !(
from tu in rmdb.t_users
from tuc in rmdb.t_user_certificates
where tu.email == username
&& tu.id == tuc.uid
&& tuc.value == tc.id select tc).AsEnumerable().Any()
select new ViewModelCheckBox()
{ Checked = false,
intconverter = tc.id,
Name = tc.name
});

How to write LINQ IN clause query which will work as LIKE operator as well?

How we can write a LINQ query for following select sql query:
string brandid="1,2,3"
string bodystyleid="1,2,3"
-------------------
-----------------
select * from car
where brandid in (brandid)
and bodystyleid in (brandid)
----------------------
-------------------
My specific requirement is that if brandid or bodystyleid is blank(if user does not select
any checkbox of a particular search option) query should return all record for that particular where condition.
Please guide me.
Thanks,
Paul
In order to fulfil your requirement about returning all items if none are specified, you need to check for the lists being empty.
var brands = brandid.Split(',').Select(x => Int32.Parse(x));
var styles = bodystyleid.Split(',').Select(x => Int32.Parse(x));
var result = from c in car
where (!brands.Any() || brands.Contains(c.brandid))
&& (!styles.Any() || styles.Contains(c.bodystyleid))
select c;
(similar to sgmoore's solution, but includes the check for no brand/style specified)
I've not actually checked how this gets converted back to SQL - it may be more efficient to use a flag to indicate whether there are any values:
var brands = ....; // As above
bool anyBrands = brands.Any()
var result = from c in car
where (!anyBrands || brands.Contains(c.brandid))
.....
Is bodystyleid meant to check brandid or bodystyleid? (I am assuming bodystyleid, however have wrote the query to match the query in the question (brandid))
As a start you could do:
var results = (from c in car
where c.brandid.Contains(brandid)
&& c.bodystyleid.Contains(brandid)
select c).ToList();
var brandids = brandid .Split(',').Select(n => int.Parse(n)).ToList();
var bodyStyleids = bodystyleid.Split(',').Select(n => int.Parse(n)).ToList();
var results =
(from c in car where
brandids.Contains(c.brandid) &&
bodyStyleids.Contains(c.bodystyleid)
select c
).ToList();
the Ids you have are as strings with comma delimiter, you need them to be collections like List of the same type as your Ids of the Car table, so if brandid column is int then brandids has to be List<long>, then you can do
var results = (
from c in cars
where brandids.Contains(c.brandid) && bodystyleid.Contains(c.bodystyleid)
select c).ToList();

LINQ - using a query expression to calculate data time difference

I use EntityFramework 4, LINQ, and C#.
I need display data in a GridView from a query expression using Linq; I need project as anonymous type a value calculate on fly DateTime.UtcNow - cl.DateLocked Note: cl.DateLocked is of type DateTime and I need to know how many days of difference between this two dates.
With this query I receive an error:
DbArithmeticExpression arguments must have a numeric common type.
Any idea how to do it in Linq? If Linq does not allow it how to do it in a different way?
Thanks for your time
var queryContentsLocked = from cl in context.CmsContentsLockedBies
join cnt in context.CmsContents
on cl.ContentId equals cnt.ContentId
join u in context.aspnet_Users
on cl.UserId equals u.UserId
select new
{
cl.DateLocked,
cnt.ContentId,
cnt.Title,
u.UserName,
u.UserId,
TimePan = DateTime.UtcNow - cl.DateLocked // Problem here!!!
};
var queryContentsLocked = from cl in context.CmsContentsLockedBies
join cnt in context.CmsContents
on cl.ContentId equals cnt.ContentId
join u in context.aspnet_Users
on cl.UserId equals u.UserId
select new
{
cl.DateLocked,
cnt.ContentId,
cnt.Title,
u.UserName,
u.UserId,
Days = SqlFunctions.DateDiff("day", cl.DateLocked, DateTime.UtcNow)
};
Without using any SqlFunction
var grandTotalWork = (from t in db.AssignmentHandymandetails
join ad in db.AssignmentDetails on t.assignment_detail_id equals ad.assignment_detail_id
where ad.assignment_id == Convert.ToInt32(Label_assignmentId.Text)
select new { startTime = t.started_time.Value.TimeOfDay, endTime = t.end_time.Value.TimeOfDay, TotalWorkTime = (t.started_time.Value.TimeOfDay.Duration() - t.end_time.Value.TimeOfDay.Duration()).Duration()});
then you can bind the result in GridView you wish
Try this:
DateTime.UtcNow.Subtract(cl.DateLocked).TotalDays

Resources