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();
Related
How to convert store procedure to linq in nopCommerce c#
My store procedure query
SELECT p.Id
FROM Product p WITH (NOLOCK)
LEFT JOIN Discount_AppliedToProducts dap WITH (NOLOCK)
ON p.Id = dap.Product_Id
LEFT JOIN Product_Category_Mapping pcm WITH (NOLOCK)
ON p.Id = pcm.ProductId
LEFT JOIN Discount_AppliedToCategories dac WITH (NOLOCK)
ON pcm.CategoryId = dac.Category_Id
AND dac.Category_Id IN (1 ,2 ,3 ,4 ,5 ,6)
LEFT JOIN Product_Manufacturer_Mapping pmm WITH (NOLOCK)
ON p.Id = pmm.ProductId
LEFT JOIN Discount_AppliedToManufacturers dam WITH (NOLOCK)
ON pmm.ManufacturerId = dam.Manufacturer_Id
WHERE dap.Discount_Id IN (3)
OR dac.Discount_Id IN (3)
OR dam.Discount_Id IN (3)
My linq query
var productlist = (from q in _productRepository.Table
select q).ToList();
var discount_AppliedToProductIds = (from dp in _discountRepository.Table
from p in dp.AppliedToProducts
select p).ToList().DistinctBy(d => d.Id).ToList();
var discount_AppliedToCategorieIds = (from dp in _discountRepository.Table
from c in dp.AppliedToCategories
select c).ToList().DistinctBy(d => d.Id).ToList();
var discount_AppliedToManufacturerIds = (from dp in _discountRepository.Table
from m in dp.AppliedToManufacturers
select m).ToList().DistinctBy(d => d.Id).ToList();
var product_Manufacturer_Mapping = (from dp in productlist
from pm in dp.ProductManufacturers
select pm).ToList().DistinctBy(d => d.Id).ToList();
var product_Category_Mapping = (from dp in productlist
from pc in dp.ProductCategories
select pc).ToList().DistinctBy(d => d.Id).ToList();
var ss = (from p in productlist
join dap in discount_AppliedToProductIds on p.Id equals dap.Id
join pcm in product_Category_Mapping on p.Id equals pcm.ProductId
//join dac in discount_AppliedToCategorieIds on pcm.CategoryId equals dac.Id
from dac in discount_AppliedToCategorieIds
join pmm in product_Manufacturer_Mapping on p.Id equals pmm.ProductId
join dam in discount_AppliedToManufacturerIds on pmm.ManufacturerId equals dam.Id
from dapd in dap.AppliedDiscounts
from pacd in dac.AppliedDiscounts
from damd in dam.AppliedDiscounts
where discountIds.Any(d => dapd.Id == d || d == pacd.Id || d == damd.Id)
// innner join condition
where categoryIds.Any(d => d == dac.Id) && dac.Id == pcm.CategoryId
select p).ToList();
I have write this code into c# but this code not provide proper result. Now I don't know what is problem into this code. If I run this code into sql server, then I get proper result, but in c# code I don't get proper result.
It's been a long time since I wrote a query in LINQ, but I seem to recall that if you wish to model a LEFT JOIN, you have to use DefaultIfEmpty(), otherwise you end up with an INNER JOIN.
See this, it's answer shows where to apply DefaultIfEmpty:
Linq join iquery, how to use defaultifempty
Obviously if you don't correctly model a LEFT JOIN expression, you'll end up with results only when all 3 inputs produce values.
I would also suggest not using .ToList() on each of your source queries, because that's going to manifest data into memory and use LINQ to Objects for your final query. If you remove the .ToList(), LINQ will construct a single database query for the entire process.
Mark
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
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();
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()
SELECT * FROM register WHERE user_id LIKE 'a%'
SELECT * FROM register WHERE user_id LIKE '%m'
SELECT * FROM register WHERE user_id LIKE '%andru%'
SELECT R.name,C.country_name,S.state_name
FROM register R JOIN country C ON R.country_id=C.country_id
JOIN state S ON R.state_id=S.state_id
SELECT R.name,C.country_name,S.state_name
FROM register R INNER JOIN country C ON R.country_id=C.country_id
INNER JOIN state S ON R.state_id=S.state_id
Now i need LinqToSql Queries instead of these query
var result = context.Registers.Select(x => x.StartsWith(foo)).ToList();
result = context.Registers.Select(x => x.EndsWith(foo)).ToList();
result = context.Registers.Select(x => x.Contains(foo)).ToList();
result = from register in context.Registers
join state in context.States on register.state_id equals state.state_id
select new { register.name, state.country_name, state.state_name }
Note, inner join and join function the same in SQL — thus no need to complicate.