Linq to SQL - Group By and Count - c#

I'm trying to convert this query (already working)
SELECT Building.NAME, COUNT([User].ID)
FROM BuildingUser
INNER JOIN Building ON Building.ID = BuildingUser.ID_BUILDING
INNER JOIN [User] ON [User].ID = BuildingUser.ID_USER
GROUP BY Building.NAME
To Linq to SQL, but I don't know what I'm doing wrong. Look at my trying
from buildinguser in db.GetTable<BuildingUser>()
join building in db.GetTable<Building>()
on buildinguser.ID_BUILDING equals building.ID
join user in db.GetTable<User>()
on buildinguser.ID_USER equals user.ID
group building by building.NAME into grpBuilding
select new
{
building = grpBuilding.Key,
users =
};
I just need to group my Buildings and count how many users each one has.

Simply use the the Count method:
from buildinguser in db.GetTable<BuildingUser>()
join building in db.GetTable<Building>()
on buildinguser.ID_BUILDING equals building.ID
join user in db.GetTable<User>()
on buildinguser.ID_USER equals user.ID
group building by building.NAME into grpBuilding
select new
{
building = grpBuilding.Key,
users = grpBuilding.Count()
};

Related

Having trouble with Group by and Join EF c#

I am having trouble converting this T-SQL code into EF C#
select
se.pcname, count(u.usrid) as total
from
tbusers as u
inner join
tbhcontainer as hc on u.hcid = hc.hcid
inner join
tbusersettings as se on hc.sid = se.sid
where
day(u.created) = 18
group by
se.pcname
order by
total desc
tbusers:
Username, PCName, Usrid, Created, HCID
tbhcontainer:
hcid, sid
tbusersettings:
sid, pcname
EDIT 1:
DateTime yesterday = DateTime.UtcNow.Date.AddDays(-1).AddHours(-3);
DB_121002_psmainEntities ctx = new DB_121002_psmainEntities();
var res = from r in ctx.tbusers
join hc in ctx.tbhcontainers on r.hcid equals hc.hcid
join s in ctx.tbUserSettings on hc.sid equals s.sid
group s by s.pcname
where r.created >= yesterday || r.created <= DateTime.Today
select r;
return res.Count();
It fails on all levels, just don't know how to use group by with joined tables
A direct translation would look more like this:
from u in ctx.Users
join hc in ctx.HContainers on u.Hcid equals hc.Hcid
join us in ctx.UserSettings on hc.Sid equals us.Sid
where u.Created.Day == 18
group u.Userid by us.Pcname into g
let total = g.Count()
orderby total descending
select new
{
pcname = g.Key,
total,
}
If you have additional clauses after the grouping, you need to place the results into another variable (g). Then you can access the group key and perform any aggregating function on that group.

LINQ syntax for SQL query with multiple inner joins and aliases

I am working on creating a C# LINQ statement from a SQL query with multiple joins and aliases. I am having some trouble constructing the LINQ.
The SQL:
SELECT
store.Name as 'Store',
store.CreatedOn as 'StoreCreated',
supplier.Name as 'Supplier',
supplier.CreatedOn as 'SupplierCreated',
farm.Name as 'Farm',
farm.CreatedOn as 'FarmCreated',
FROM Users store
INNER JOIN UserRelationship toSupplier on store.ID = toSupplier.YId
INNER JOIN Users supplier ON supplier.ID = toSupplier.XId
INNER JOIN UserRelationship toFarm ON store.ID = toFarm.XId
INNER JOIN Users farm ON farm.ID = toFarm.YId
WHERE
store.Active= '1'
AND
supplier.Active = '1'
AND
farm.Active = '1'
This returns rows showing the relationships between the three parties and the dates.
So, far, I've got the following LINQ:
var newUserList = from store in Users
join toSupplier in UserRelationship on store.ID = toSupplier.YId
join supplier in Users on supplier.ID = toSupplier.XId
join toFarm in UserRelationship on store.ID = toFarm.XId
join farm in Users on farm.ID = toFarm.YId
Am I on the right track? Any help would be appreciated.
LINQ join syntax uses equals keyword instead of = in join condition:
var newUserList = from store in Users
join toSupplier in UserRelationship on store.ID equals toSupplier.YId
join supplier in Users on supplier.ID equals toSupplier.XId
join toFarm in UserRelationship on store.ID equals toFarm.XId
join farm in Users on farm.ID equals toFarm.YId
select ...

translate postgres sql to linq. Is it possible?

I need translate next sql to linq is it possible? That will have approximately the same speed
SELECT Count(tblcollectionimage.lngimageid),
tblcollectiontree.lngcollectionid,
tblcollection.txtname
FROM (tblcollectiontree
LEFT JOIN tblcollectionimage
ON blcollectiontree.lngcollectionid =
tblcollectionimage.lngcollectionid)
JOIN tblcollection
ON tblcollectiontree.lngcollectionid = tblcollection.lngcollectionid
WHERE lngcollectionparentid = 0
GROUP BY tblcollectiontree.lngcollectionid,
tblcollection.txtname
I have currently such linq but it doesn't work.
var results =(from collection in dataBase.tblcollections
join collectionTree in dataBase.tblcollectiontrees on
collection.lngcollectionid equals collectionTree.lngcollectionid
into generalCollections
from generalCollection in generalCollections
join images in dataBase.tblcollectionimages on
collection.lngcollectionid equals images.lngcollectionid
into generalCollectionImages
from generalCollectionImage in
generalCollectionImages.DefaultIfEmpty()
group generalCollectionImage by
generalCollectionImage.lngcollectionid into hello
from hellos in hello.DefaultIfEmpty()
join collection in dataBase.tblcollections on
hello.Key equals collection.lngcollectionid
select new
{
id = hello.Key,
name = hello.Count()
}).ToList();

LEFT LINQ TO SQL C# JOIN on many to many table

Hi im kinda new to linq to sql I know about the basics. The problem is I want to do a left join in a query. There are 3 tables in the query.
Claimants ( all rows should be returned from this table)
Claim
User
The query should return all Users who have Claimants. This is done through the many to many table Claim. But regardless of Users all Claimants should be returned. Thus the left join on Claimants.
I have the following query
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
I have tried using an into statement as follows but with no luck
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID
into TheClaimants
from Claims in TheClaimants.DefaultIfEmpty()
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
I would appreciate it if someone could point me in the right direction as to how to use these joins left right correctly and explain how the work. Thank you very much in advance.
var d = (from Claimants in DB.Claimants
join Claims in DB.Claims on Claimants.Claiment_ID equals Claims.Claiment_ID)
.DefaultIfEmpty()
join Users in DB.Users on Claims.User_ID equals Users.User_ID
where (Claimants.TrialDate.Value >= dtDayStart & Claimants.TrialDate <= dtDayEnd)
.DefaultIfEmpty()
select new
{
ClaimantFirstName = Claimants.FirstName,
ClaimantLasname = Claimants.LastName,
ClaimantsID = Claimants.IDNumber,
Claimants.OurReference,
Claimants.TrialDate,
InterviewStart = Claims.DateTimeStart,
InterviewEnd = Claims.DateTimeEnd,
Claims.Priority,
UserFirstname = Users.FirstName,
UserLastName = Users.LastName,
UserID = Users.IDNumber
});
Left outter join
You must know a Luan. If you want all the Claiments to return start by selecting from Claiments and then left join onto the other tables.
Try the following :
LINQ to SQL Left Outer Join
In LINQ, the ".Join()" extension method is the equivalent of SQL inner join.
For outer joins you have to use the ".GroupJoin()" extension method.
Assuming you know the .Join well, the GroupJoin is simple to use. I have to admit that when I first needed to do an outer join in LINQ it was damn hard to find out. I cannot fanthom why did they call it like that.
Although in VB.Net, here's an article that presents various SQL constructs translated into LINQ syntax, even if in VB, still easy to convert to extension methods: http://blogs.msdn.com/b/vbteam/archive/2007/12/31/converting-sql-to-linq-part-6-joins-bill-horst.aspx?Redirected=true
EDIT: #DavidB posted in his comments a much better solution, but only if you can use some ORM navigational properties. If you don't have them, then GroupJoin is probably the most reasonable

Can't convert T-SQL INNER JOIN to LINQ-Entities query

T-SQL:
declare #postlocations table (locationid int)
insert into #postlocations
select locationid
from dbo.PostLocations
where PostId = 162172
select t.*
from dbo.Themes t
inner join dbo.ThemeLocations tl on t.ThemeId = tl.ThemeId
inner join #postlocations pl on tl.LocationId = pl.locationid
LINQ-Entities i have so far:
var postLocations = e.SomePost.Locations; // pre-fetched, e.g materialized ICollection<Post>
var themes = (from t in db.Themes
join q in postLocations on t.Locations.Select(l => l.LocationId) equals q.LocationId
select t).ToList();
But the compiler is complaining on the join keyword about not being able to infer the type arguments.
Any ideas?
I don't think you can join a SQL table with an in-memory list of objects, even if those objects are originally from the database.
Convert the in-memory list of objects to a list of id's (integer), and use that in the join or in a Contains/sub-select. EF can translate the list of id's to parameters when generating the SQL.
The problem with your join is that you're implying a collection of LocationId (t.Locations.Select(l => l.LocationId) can equal a single LocationId. You're trying to join a Theme which has a collection of Locations onto a single Location.
You should be able to fix this by using Contains
var themes = (from t in db.Themes
join q in postLocations
on t.Locations.Select(l => l.LocationId).Contains(q.LocationId)
select t).ToList();
or if EF complains about passing a postLocations as a parameter, you can try
// I'd materialize this but you may not have to
var postLocationIds = postLocations.Select(p => p.LocationId).ToList();
var themes = db.Themes.Where(t => t.Locations.Any(l =>
postLocationIds.Contains(l.LocationId))).ToList();
Edit
how about this
///your sql query
select t.* from dbo.Themes t
inner join dbo.ThemeLocations tl on t.ThemeId = tl.ThemeId
inner join #postlocations pl on tl.LocationId = pl.locationid
//linq query for that
from t in teams
join from tl in teamlocation on t.themid = tl.ThemeID
join from pl in postlocation on tl.temeid = pl.temeid
select t;
Org
Not sure but you can try out by using let keyword
var themes = (from t in db.Themes
let location = t.Locations
join q in postLocations on location.LocationId equals q.LocationId
select t).ToList();

Categories

Resources