I'm a junior developer and trying to convert the following linq statement to T-SQL:
var items = from u in DataContext.Users_SearchUsers(searchPara.UserFirstName,
searchPara.UserLastName,
searchPara.UserEmailAddress,
fetchOptions.page,
fetchOptions.rp,
fetchOptions.sortname,
fetchOptions.sortorder)
.ToList()
join a in DataContext.UserAccesses
.Where(x => x.Access.AccessTypeId == 4).ToList() on u.UserID equals a.UserId into accessGroup
select new {};
Can one please help me ? into accessGroup ---> (very important)
First of all you need to understand where your data is coming from. You are loading information from Users_SearchUsers on the one hand and UserAccesses on the other hand. The first query looks like
select <somecolumns>
from users
where <somefilters>;
(you need to use your actual columns and criteria, but Users_SearchUsers is not specified in the question at all). I have ignored paging here for the sake of simplicity
The second query looks like this:
select *
from user_accesses
where access_type_id = 4;
Let's join the two:
select <someoutercolumns>
from
(
select <someinnercolumns>
from users
where <somefilters>
) t1
join
(
select <someotherinnercolumns>
from user_accesses
where access_type_id = 4
) t2
on t1.user_id = t2.user_id;
These queries are probably not the exact solutions you need, but you want the answers to improve, then improve your question.
The requirement makes sense if the LINQ query is very slow. In that case you will need to refactor it in the following manner:
select <somecolumns>
from users
join user_accesses
on users.user_id = user_accesses.user_id and user_accesses.access_type_id = 4
where <somefilters>;
you can use this code
select *(you can put your columns instead *)
from Users
join UserAccesses
on Users.userid = UserAccesses.userid
where UserAccesses.typeid = 4;
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have many to many relationship, table Product, table Category and join table ProductCategory.
I need to convert this SQL query to LINQ C#:
Select TOP 3 Categories.id, Categories.Description, avg(Products.Price) as MeanPrice, count(Products.IsAvailable) as NumberOfAvailableProducts
FROM Categories
INNER JOIN ProductCategories on Categories.Id =
ProductCategories.CategoryId
INNER JOIN Products on Products.Id = ProductCategories.CategoryId
WHERE Products.IsAvailable='true'
GROUP BY Categories.Id, Categories.Description
ORDER BY MeanPrice DESC
I would appreciate help, thanks.
There are so many examples in the Internet for you to start learning how to write LINQ effectively (including the post from NetMage above).
But I would give you the examples anyway, based on your case above, with an assumption that this T-SQL of yours :
INNER JOIN Products on Products.Id = ProductCategories.CategoryId
might've been a typo, because what you really meant was maybe like this :
INNER JOIN Products on Products.Id = ProductCategories.ProductId
So, this is the snippet when you ask me how could I do that in LINQ :
var query = (from finalq in
(
from cat in categories
join procat in
// Join [ProductCategories] with [Products] first
(
from pc in productcategories
join p in products on pc.ProductId equals p.Id
where p.IsAvailable == "True"
select new
{
CategoryId = pc.CategoryId,
ProductId = p.Id,
ProductPrice = p.Price
}
)
// And then join the result with [Categories]
on cat.Id equals procat.CategoryId
select new
{
CategoryId = cat.Id,
CategoryDescription = cat.Description,
ProductPrice = procat.ProductPrice
}
)
// Then aggregate it to get the final result
group finalq by new { finalq.CategoryId, finalq.CategoryDescription } into finalGroup
orderby finalGroup.Average(c => c.ProductPrice) descending
select new
{
CategoryId = finalGroup.Key.CategoryId,
CategoryDescription = finalGroup.Key.CategoryDescription,
ProductPrice = finalGroup.Average(c => c.ProductPrice),
NumberOfAvailableProducts = finalGroup.Count()
}
)
// And take the TOP 3 rows (I know it's ugly but I don't have a choice)
.Take(3);
So, that's it. I hope you can get something from my post here, and later may create your own, a better version of this quick example.
Good luck!
For translating SQL to LINQ query comprehension:
Translate FROM subselects as separately declared variables.
Translate each clause in LINQ clause order, translating monadic operators (DISTINCT, TOP, etc) into functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { ... }) for multiple columns.
Left Join is simulated by using a into join_variable and doing another from from the join variable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator and a null test.
Translate IN to .Contains() and NOT IN to !...Contains()
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
SELECT fields must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Proper FULL OUTER JOIN must be handled with an extension method.
I'm brand new to .net MVC, and while I have some basic experience with writing SQL queries, I'm not sure how to go about what I need to do for .NET.
My initial query looks like this:
var results = (from s in db.Members
join sa in db.FocusArea on s.ID equals sa.MemberID
where sa.Area == SearchString
select new { s.ID, s.Name, s.Overview }).ToList();
This is not functioning correctly. It is seaching in the s.Overview for some reason. And, I need to make this query much more complicated. In short, I have three tables I need to search across. And with this query, it is not working:
var conceptResults = (from s in db.Cohorts
join oa in db.OutcomeArea on s.ID equals oa.CohortID
where ((oa.Area.Contains(SearchString))
|| (oa.OutcomeType.Contains(SearchString)))
select new { s.ID, s.Name, s.Overview }).ToList();
I need to use my SearchString to search for matches in both Area and Description in db.FocusArea.
I also need to use my SearchString to search for matches (contains) in another table db.SpecificFocusAreas for column SFocusArea where again the join is the ID/MemberID.
Is there a way to essentially do a join or join type of statement? I don't want to join all three tables because I am looking for results from either of the two joins, not from all joins.
I am trying to figure out how to get all the notifications from relations that get multiple notifications, because i want to combine these notifications to 1 notification so the relation wil only get 1 e-mail instead of multiple.
I created the following SQL statement, which for as far as i can tell does what i want:
select distinct r.Notificatie
, r.RelatieNr
FROM [configuratie].[dbo].[NotificatieRecID] r
join [configuratie].[dbo].[Notificatie] n on r.Notificatie = n.ID
where n.Verzonden = 0
and r.RelatieNr in(select RelatieNr from [configuratie].[dbo].[NotificatieRecID]
group by RelatieNr having count(*) > 1)
order by r.RelatieNr
It returns the following
Notification Relation
3A2A53B9-D92A-4504-874D-5A901AD01041 114147
4C499F6C-53C8-49E0-B529-8B045819BE10 114147
AF4ED8CB-D033-47A4-96AE-F379BB484532 114147
977885C5-4C12-431B-AB72-59383B1824C6 303327
3A2A53B9-D92A-4504-874D-5A901AD01041 303327
4C499F6C-53C8-49E0-B529-8B045819BE10 303327
AF4ED8CB-D033-47A4-96AE-F379BB484532 303327
Later in my c# code i will get all the values from the different notifications and simply combine them but first i need to write this SQL statement in a way i can use it with linq in c#.
I have no idea how to do SELECT DISTINCT, and r.RelatieNr in and group by RelatieNr having count(*) > 1
Could someone provide me with an example? (it does not have to be 1 linq statement, i've kind of figured that's impossible, though i would like as little temporary Lists/Iqueriables since the tables are huge)
You can use the following
var details= (from r in NotificatieRecID
join n in Notificatie on r.Notificatie=n.ID
where n.Verzonden=0 &&
(from t in NotificatieRecID
group t by t.RelatieNr into grp
where grp.Count()>1
select grp.Key).Contains(r.relatieNr)
select new {
Notificate=r.Notificatie,
RelatieNr=r.RelatieNr
}).Distinct();
This might be one of those situations where plain SQL commands are better than LINQ. Here's a simplified version of the SQL statement I'm trying to translate:
SELECT * FROM IDTable AS idt
INNER JOIN NameTable AS nt ON nt.IDTableID=idt.Id
AND nt.Id= (SELECT TOP(1) Id
FROM NameTable AS nt2
WHERE nt2.IDTableID=11 ORDER BY nt2.DateInserted DESC)
I have the LINQ query to pull records when just joining on IDs and I've seen how to join on multiple columns, but I have no idea how to plug the subquery into the mix.
If this isnt entirely clear, please let me know and I'll edit to elaborate.
Maybe something like this?
var results = from id in db.IDTable
join n in db.NameTable on id.Id equals n.IDTableID
where n.Id = (
from n2 in db.NameTable
where n2.IDTableID = 11
orderby n2.DateInserted desc
).First()
select new { id, n };
I have this hql query, which works perfect:
select m
from Media m
join m.Productlines p
join m.Categories c
join m.Spaces sp
join m.Solutions so
where m.Uid != 0
and p.Uid in (:productlines)
and c.Uid in (13)
and sp.Uid in (52)
and so.Uid in (15,18)
group by m.Uid
But now it needs to be parameterized/made dynamic, not only the parameters, but also the joins (it is possible to select only from Media, without any joins, and so no *.Uid in will be required in this case).
I dont want to mess around with a StringBuilder instance and build the hql query that way, I would rather like to use the Criteria API, but I cant get a
SELECT m.*
....
GROUP BY m.Uid
query to work with Criteria.
If I add a
Projections.GroupProperty("Uid")
to my query, nhibernate selects
SELECT m.Uid
....
GROUP BY m.Uid
which is of course wrong.
After that, I also need to count the unique rows the query returned, as the result is paged.
So, my other query is quite similiar, but I cant find a Criteria equivalent for
SELECT COUNT(DISTINCT m.Uid)
Here is the HQL:
select count(distinct m.Uid)
from Media m
join m.Productlines p
join m.Categories c
join m.Spaces sp
join m.Solutions so
where m.Uid != 0
and p.Uid in (:productlines)
and c.Uid in (13)
and sp.Uid in (52)
and so.Uid in (15,18)
How can this be done with Criteria API?
Please, (N)Hibernate experts - help me with this, I cant find a working solution. Any help is greatly appreciated!
Group columns are implicitly returned as result, but you can add more columns. AFAIK, you can return full entities:
var query = session.CreateCriteria(typeof(Media), "m")
.Add(Projections.GroupProperty("m"))
.Add(Restrictions.NotEq("m.Uid", 0));
// dynamically add filters
if (filterProductLines)
{
query
.CreateCriteria("m.Productlines", "p")
.Add(Restrictions.Eq("p.Uid", productLines));
}
// more dynamic filters of this kind follow here...
IList<Media> results = query.List<Media>();
To count the full number of results you can just build up the same query with different projection:
var query = session.CreateCriteria(typeof(Media), "m")
.SetProjection(Projections.CountDistinct("m.Uid"));
// rest of the query the same way as above
long totalNumberOfResults = query.UniqueResult<long>();
I'm getting unsure about the Projections.GroupProperty("m"), you need to try this. If it doesn't work, you could make it an DetachedQuery that only returns ids:
var subquery = DetachedCriteria.For(typeof(Media), "m")
.Add(Projections.GroupProperty("m.Uid"))
.Add(Restrictions.NotEq("m.Uid", 0));
// add filtering
var query = session.CreateCriteria(typeof(Media), "outer")
.Add(Subqueries.PropertyIn("outer.Uid", subquery));
IList<Media> results = query.List<Media>();
This creates a sql query like this:
select outer.* // all properties of Media to create an instance
from Media outer
where outer.Uid in (
select Uid
from media m
where // filter
)
var count = session.CreateCriteria(typeof(Media))
// Add other criterias...
.SetProjection(Projections.CountDistinct("Id")) // or whatever the id property of Media class is called
.UniqueResult<long>();
As to your GROUP BY question, the query:
SELECT m.*
....
GROUP BY m.Uid
makes no sense because you need to select only columns that appear in the group by clause or aggregate functions. Could you elaborate a little more as to what exactly are you trying to achieve?