I have a database set up like so:
Lets say that I have a product group with id of 12. How do I get the CategoryID for this particular Product Group? Would I have to do a join?
Think of it in parts...
How would you do this in SQL?
SELECT DISTINCT sc.CategoryID
FROM SubCategory sc
WHERE sc.SubCategory IN (
SELEcT DISTINCT scpg.SubCategoryID
FROM SubCategoryProductGroups scpg
WHERE scpg.ProductGroupID = 12)
To do this in LINQ2SQL it would be something like this...
using (var db = new MyDataContext()) {
var query = (from sc in db.SubCategories
where (from scpg in db.SubCategoryProductGroups
where scpg.ProductGroupID == 12
select scgp.SubCategoryID).Distinct().Contains(sc.SubCategoryID)
select sc.CategoryID).Distinct();
}
... You could also use joins ...
SQL...
SELECT DISTINCT sc.CategoryID
FROM SubCategory sc
JOIN SubCategoryProductGroups scpg ON sc.SubCategoryID = scpg.SubCategoryID
WHERE scpg.ProductGroupID = 12
LINQ2SQL...
var query = (from sc in db.SubCategories
join scpg in db.SubCategoryProductGroups
on sc.SubCategoryID equals scpg.SubCategoryID
where scpg.ProductGroupID == 12
select sc.CategoryID).Distinct();
... If you LINQ model knows of the relationship you could probably do this ...
var query = (from sc in db.SubCategories
where sc.SubCategoryProductGroups
.Any(s=>s.ProductGroupID == 12)
select sc.CategoryID).Distinct();
dc.subcatogorysproductsgroups.where(o=> o.productgroupid == 12).select(j=> o.subcatogory.catogory);
one thing is if u r using linq to sql then there is no need of using join if the database if fully normilized.
and before using this code ensure the dc.defferedloadingenabled is set to be true.
or use DataLoadOptions and Dc.loadPropery
Hope this helps
var result = from sc in SubCategory
join scpg in SubCategoryProductGroups
on sc.SubCategoryID equals scpg.SubCategoryID
where scpg.ProductsGroupID =12
select sc.CategoryID
Related
I am having problems in writing a LINQ for calculating average value based on not directly referenced column.
Provide background and tell us what you've already tried.
I have following tables, now I want average marks based on category and subcategory, But fetching it through TopicId(FK) in Result table is going to be a big task.
(I tried and couldn't figure out how to do it)
Image having tables
How Can I get average marks for Category and subcategory?
This is the SQL query that you need:
select
c.Id as CategoryId,
c.CategoryName,
sc.Id as SubCategoryId,
sc.SubCategoryName,
AVG(r.Marks) as Average
from Result r
join Topic t on r.TopicId = t.Id
join SubCategory sc on t.SubCategoryId = sc.Id
join Category c on sc.CategoryId = c.Id
group by c.Id, c.CategoryName, sc.Id, sc.SubCategoryName
And this is the same with LINQ query syntax:
using (var db = new TopicContext())
{
// build the query
var query =
from r in db.Result
join t in db.Topic on r.TopicId equals t.Id
join sc in db.SubCategory on t.SubCategoryId equals sc.Id
join c in db.Category on sc.CategoryId equals c.Id
group r by new { c.Id, c.CategoryName, SubCategoryId = sc.Id, sc.SubCategoryName } into gr
select new
{
CategoryId = gr.Key.Id,
CategoryName = gr.Key.CategoryName,
SubCategoryId = gr.Key.SubCategoryId,
SubCategoryName = gr.Key.SubCategoryName,
Average = gr.Average(x => x.Marks)
};
// ToList() method executes the query, so we get the result on that line of code
var result = query.ToList();
}
If you have an existing database you can use EF Core to generate your own dbContext (in my example this is TopicContext class) with the help of Scaffold-DbContext command. You can find an example of this command on that page. To use this command you should install Microsoft.EntityFrameworkCore.Tools nuget package along with Microsoft.EntityFrameworkCore.SqlServer.
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();
This is my SQL command
SELECT KEY,NAME
from COMPANY c
WHERE KEY IN (select KEY from USER_COMPANY where UserId = #UserId)
order by NAME asc
So I want to convert it to Entity Framework.
I try like this
var userCompany = (from u in db.USER_COMPANY
where u.UserId == UserId
select(u.KEY));
var user = (from c in db.COMPANY
where (c => userCompany.Contains(c.KEY)
select c);
but it is not working.
How to use the SQL IN keyword in Entity Framework?
Try this:
var query = from c in db.COMPANY
where (from u in db.USER_COMPANY
where u.UserId == UserId
select u.KEY).Contains(c.KEY)
orderby c.NAME
select c.KEY, c.NAME;
Note that this SQL query has the exact same meaning:
SELECT c.KEY, c.NAME
FROM COMPANY c
JOIN (SELECT DISTINCT KEY FROM USER_COMPANY where UserId = #UserId) u
ON U.KEY = C.KEY
ORDER BY c.NAME asc
So you should be able to just do:
var userCompany = (from u in db.USER_COMPANY
where u.UserId == UserId
select(u.KEY)).Distinct();
var result = from c in db.COMPANY
join u in userCompany
on c.KEY = u.KEY
select new {c.KEY, c.NAME};
My understanding is that the translation from .Contains() to IN is only just being added to EF6.
According to this work item (http://entityframework.codeplex.com/workitem/245) and the release note: Improved performance of Enumerable.Contains in LINQ queries.
So look for it in EF6
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();
How do I write this SQL in Linq to SQL using C#. I cannot get the join to the status table to both ConsumerApplications and RepairOrderEstimates to work properly. Thanks.
select ca.ConsumerAppID,
ca.LastName,
statConsumerApp.StatusName,
statRepairOrderEstimates.StatusName
from ConsumerApplications ca
join RepairOrderEstimates
on ca.RepairOrderEstimateID = RepairOrderEstimates.RepairOrderEstimateID
join Statuses statConsumerApp
on ca.StatusID = statConsumerApp.StatusID
join Statuses statRepairOrderEstimates
on RepairOrderEstimates.StatusID = statRepairOrderEstimates.StatusID
I think you can do this with something like
from ca in ConsumerApplications
join est in RepairOrderEstimates on ca.RepairOrderEstimateID == est.RepairOrderEstimateID
join statConsumerApp in Statuses on ca.StatusID == statConsumerApp.StatusID
join statEstimate in Statuses on est.StatusID == statEstimate.StatusID
select new {
ConsumerAppID = ca.ConsumerAppID,
LastName = ca.LastName,
AppStatus = statConsumerApp.StatusName,
EstimateStatus = statEstimate.StatusName,
}