translate postgres sql to linq. Is it possible? - c#

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();

Related

Linq query showing more data than the SQL alternative

I have an linq query like this :
var query = from Romm in RoMM
join rfrsa in RoMmfrsa on Romm.RoMmid equals rfrsa.RoMmid
join frsa in Frsa on rfrsa.Frsaid equals frsa.Fraid
join fra in Fra on frsa.Fraid equals fra.Fraid
where Romm.ActTypeId == 2 && Romm.SegmentId == 4
select new
{
Romm.ActTypeId,
Romm.RoMmid,
frsa.Fraid,
frsa.Frsaid,
Romm.ImpactId
};
And I have SQL code as below :
SELECT romm.ROMMID
, frsa.FRAID
, frsa.FRSAID
, romm.ImpactID
FROM RoMM AS romm
INNER
JOIN RoMMFRSA AS rfrsa
ON romm.RoMMID = rfrsa.RoMMID
INNER
JOIN FRSA AS frsa
ON rfrsa.frsaid = frsa.frsaid
INNER
JOIN FRA AS fra
ON frsa.FRAID = fra.FRAID
WHERE romm.acttypeid = 2
AND romm.segmentid = 4
The SQL only shows one row (which is correct), the linq shows the correct row and then it displays about another 3 rows which is not what we need. I need the linq to show one row which is correct with the SQL. Is this because of maybe many-many relationships ?
Looks like a typo in either the C# or the SQL join:
SQL: ON rfrsa.frsaid = frsa.frsaid
C#: rfrsa.Frsaid equals frsa.Fraid
^^^^^^
mismatch here

How to translate this inner join T-SQL into LINQ-to-Entities?

I have a snippet of Stored Procedure:
...
SELECT B.BinID, AverageCost, SUM(Qty) AS Qty
FROM #CurrentReturn R INNER JOIN Bins B ON R.BinCode = B.BinCode AND B.StoreroomID = #StoreroomID
...
#StorerroomID is one of the SP parameters.
Now I am trying to translate it into LINQ to Entities,
var AverageCostList = from r in CurrentReturn
join b in BinQuery on new {r.BinCode, b.StoreroomID} equals new {b.BinCode, storeroomID}
It does not work, as the type on the L.H.S. of equals cannot contains fields in b.
So is there any way to translate such an inner join SQL into LINQ?
i would put the B.StoreroomID = #StoreroomID comparison into ther where clause
from r in CurrentReturn
join b in BinQuery
on r.BinCode equals b.BinCode
where b.StoreroomID == storeroomID

Left outer join and multiple counts SQL to LINQ

How would this query using an inner join, left outer join, group by and two counts be converted to linq?
SELECT
c.EndowmentID,
COUNT(DISTINCT f.CriterionID) AS RequiredCriteria,
COUNT(r.ChoiceID) AS Response
FROM
Criteria c
INNER JOIN
Filters f
ON
c.ID = f.CriterionID
LEFT OUTER JOIN
Responses r
ON
f.ChoiceID = r.ChoiceID
WHERE
f.IsRequirement = 1
GROUP BY
c.EndowmentID;
This is what I have done so far:
var result =
from c in context.Criteria
join f in context.Filters on c.ID equals f.CriterionID
join r in context.Responses on f.ChoiceID equals r.ChoiceID into resfil
from rf in resfil.DefaultIfEmpty()
group rf by c.EndowmentID into grouped
select new
{
EndowmentID = grouped.Key,
Requirements = grouped.Count(t=>t.CriterionID),
Response = grouped.Count(t=>t.ChoiceID)
};
You need to group using an anonymous class. This will allow you to access all your tables in your select statement
group new { c, f, rf } by c.EndowmentID into grouped
SQL: COUNT(DISTINCT f.CriterionID) AS RequiredCriteria,
This can be written by first selecting the f.CriterionID column, Distinct(), Count()
RequiredCriteria = grouped.Select(x => x.f.CriterionID).Distinct().Count()
SQL: COUNT(r.ChoiceID)
Response = grouped.Select(x => x.rf.ChoiceID).Count()

Linq to SQL - Group By and Count

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()
};

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