SQL to LINQ for SubQuery Entity Framework - c#

i want to convert this SQL to LINQ but i cant compile it. This is my sql to convert
SELECT u.UserID ,
A.Username ,
A.Password ,
A.CreatedOn
FROM dbo.tbl_User U
INNER JOIN dbo.tbl_UserAuthDetail A ON A.UserID = U.UserID
AND A.CreatedOn IN (
SELECT TOP 1
CreatedOn
FROM dbo.tbl_UserAuthDetail U2
WHERE U2.UserID = U.UserID
ORDER BY CreatedOn DESC )
and this is my attempt so far
var q = from u in context.Users
join au in context.UserAuthDetails on u.UserID equals au.UserID &&
(from au2 in context.UserAuthDetails where au2.UserID == u.UserID orderby au2.CreatedOn descending select au2.CreatedOn).ToList().Contains(au.CreatedOn)
Any help would be appreciated.
TIA

Note: This code is untested but I think you want to get the latest credential of each user.
var query = context.Users
.GroupJoin(context.UserAuthDetails,
u => u.UserID ,
d => d.UserID,
(u, d) => new
{
User = u,
Details = d.OrderByDescending(x => x.CreatedOn).Take(1)
});
You can remove .Take(1) to get all the records of the user and still the result is sorted in descending order.

from u in context.Users
join au in context.UserAuthDetails on u.UserID equals au.UserID &&
context.UserAuthDetails.Where(au2 => au2.UserID == u.UserID)
.OrderByDescending(au2 => au2.CreatedOn)
.Select(au => au2.CreatedOn)
//.Take(1) //you have this in SQL
.Any(auc=>auc == au.CreatedOn)

Related

navigation property vs using left join

I have this linq statement where I want to convert into navigation property. The linq statement has a left join so I am not sure how to do that with the navigation property. I am using EF 6.0.0.0. I am trying to get all the MeetingPollingResponseTexts if there is values or nulls.
MeetingPollingParticipantsAnswers = (from p in db.MeetingPollingParticipants
join mp in db.MeetingPollings on p.MeetingPollingId equals mp.MeetingPollingId
join pq in db.MeetingPollingQuestions on mp.MeetingPollingId equals pq.MeetingPollingId
join pp in db.MeetingPollingParts on pq.MeetingPollingQuestionId equals pp.MeetingPollingQuestionId
join pv in db.MeetingPollingPartsValues on pp.MeetingPollingPartsId equals pv.MeetingPollingPartsId
join rt in db.MeetingPollingResponseTexts on pv.MeetingPollingPartsValuesId equals rt.MeetingPollingPartsValuesId into lj_rt
from rt in lj_rt.DefaultIfEmpty()
where p.MeetingPollingId == MeetingPollingId && p.CustomerId == CustomerId
select new Model.MeetingPollingParticipantsAnswers
{
QuestionValue = pv.QuestionValue,
MeetingPollingQuestionResponseText = rt.MeetingPollingQuestionResponseText,
}).ToList();
var meetingParticipantsAnswers = db.MeetingPollingParticipants
.Include(x => x.MeetingPolling)
.Include(x => x.MeetingPollingQuestions
.Select(q => q.MeetingPollingParts
.Select(i => i.MeetingPollingPartsValues)))
.Where(p => p.CustomerId == CustomerId && p.MeetingPollingId == MeetingPollingId).ToList();

Add 'where' clausures dynamically to linq query

I have this linq query:
var query = (from dc in context.Table1.Include(d => d.Doc)
join u in _context.Table2 on dc.IDDoc equals u.IDDoc
where dc.ID == id && u.IDUser == user.IDUser
select dc)
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id
select dc);
And I want to add more where conditions dynamically depends of a list (List ids)
What I want to achieve is something like this:
Imagine that I have a List ids = new(){1, 2, 5, 27);
What I want to do is to add that info into this part of the query to have something like this:
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id && p.ID == 1 || p.ID == 2 || p.ID == 5 || p.ID = 27
select dc)
But if next time list is List ids = new(){4}, query should look like:
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id && p.ID == 4
select dc)
Is it even possible? If not, what would be a possible solution?
Thank you
EDIT: I made up with this query because I have no clue about how to add it to my main query.
What I really have is this:
var mainQuery = _context.RootTable
.Include(i => i.Items).ThenInclude(dc => dc.Docs)
.Include(i => i.Items).ThenInclude(sg => sg.Signs)
.FirstOrDefault(m => m.ID== id);
And what I want to do is to filter the ".ThenInclude(dc => dc.Docs) with the other query. I can't figure out how to do it in a better and efficient way that with two sepparate queries.
Use Enumerable.Contains:
List<int> ids = new(){4};
....
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id && ids.Contains(p.ID) // here
select dc)
....

How to do this query using expression in LINQ?

select t.*
from Task t
inner join Project p on a.ProjectId = t.ProjectId
where p.ProjectTypeId IN ( select ptg.ProjectTypeId
from UserGroup ug
inner join ProjectTypeGroup ptg on ug.GroupId = ptg.GroupId
where ug.UserId = 1 -- MUTABLE VALUE
)
In the attempt query given by you, I don't see Task being used.
Since there is no relation between your sub-query and your main query, you should split them in to two queries:
var projTypeIds = (from ug in UserGroup
join ptg in ProjectTypGroup on ug.GroupId equals ptg.GroupId
where ug.UserId == 1
select ptg.ProjectTypeId).ToList()
Once you have your output, check for .Contains
var task = (from t in Task
join p in Project on p.ProjectId equals t.ProjectId
where projTypeIds.Contains(p.ProjectTypeId)
select t).FirstOrDefault();
I assume you need only one object from this query hence used .FirstOrDefault(), if you are expecting a list using .ToList()
You can use this.
from t in Task
join p in Project
on t.ProjectId equals p.ProjectId
let subQ = ( from ug in UserGroup
join ptg in ProjectTypeGroup
on ug.GroupId equals ptg.GroupId
where ug.UserId == 1
select ptg.ProjectTypeId)
where subQ.Contains(p.ProjectTypeId)
select t
or you can use this.
int loggedUserId = 1;
var _userGroups =
UserGroup.Join(ProjectTypeGroup,
t => t.GroupId, p => p.GroupId,
(t, p) => new {t, p})
.Where(n => n.t.UserId == loggedUserId)
.Select(s => s.p.ProjectTypeId);
var projectTypeIds =
Task.Join(Project,
t => t.ProjectId, p => p.ProjectId,
(t, p) => new {t, p})
.Where(n => _userGroups.Contains(n.p.ProjectTypeId) )
.Select(n => n.t);
projectTypeIds.ToList();

LINQ "not in" not working

I am trying to exclude items that have a.id that exists in db.AdminAdjusterStatus.
from u in db.Users
join a in db.Adjusters on u.id equals a.userID
where u.userType.ToLower() == "adjuster"
&& !(from x in db.AdminAdjusterStatus select x.adjusterID).Contains(a.id)
select new AdjusterProfileStatusItem { user = u, adjuster = a }
The code above says, "where NOT contains a.id in db.AdminAdjusterStatus.adjusterID.
The problem is, it doesn't work. I have these two entries in db.AdminAdjusterStatus:
A9EC05B5-651D-4AA7-8275-1F6BFE212C03
1BDE55D9-ED0A-4854-9D5F-B89DB17F02D2
And, the LINQ query gives me:
A9EC05B5-651D-4AA7-8275-1F6BFE212C03
1BDE55D9-ED0A-4854-9D5F-B89DB17F02D2
e21ff49c-9505-495d-b4a3-c259ee3459d6
Whereas, it should only give me:
e21ff49c-9505-495d-b4a3-c259ee3459d6
var query = from u in db.Users
from a in db.Adjusters
where u.userType.ToLower() == "adjuster" &&
u.id == a.userID &&
!db.AdminAdjusterStatus.Any(i => i.adjusterID == a.id)
...
You could try doing a Left Join and filtering on the null records. Without having data to test against I cannot say for certain on if it will work "out of the box" but I have used the following code several times for doing filtering like this:
db.Users.Join(db.Abjusters, outer => outer.id, inner => inner.userID, new { User = outer, Adjuster = inner })
.GroupJoin(DBConcurrencyException.AdminAdjusterStatus, outer => outer.Adjuster.id, inner => inner.adjusterID, new { User = outer.User, Adjuster = outer.Adjuster, Admins = inner })
.SelectMany(grp => grp.Admins.DefaultIfEmpty(), (grp, admin) => new { User = grp.User, Adjuster = grp.Adjuster, Admin = admin })
.Where(item => item.User.userType == "adjuster" && item.Admin == null)
.Select(item => new AdjusterProfileStatusItem { user = item.User, adjuster = item.Adjuster });
The GroupJoin/SelectMany combination performs a Left Join and then you can filter where the object is null which should produce the same as a NOT IN.
Thanks to everyone for their help and sorry to waste anyone's time. I realized that this line:
obj.adjusterID = '#(Url.RequestContext.RouteData.Values["id"])';
Elsewhere in my code had been sending u.id instead of a.id as I had thought that it was. Because of this, I was saving the wrong ID in my database, thus resulting in the problem I was experiencing.
Thanks, again for all your help!
Perhaps this could work?
var AdjusterItems = from aa in AdminAdjusterStatus
join a in Adjusters
on aa.AdjusterId equals a.AdjusterId
select a.UserId;
var UsersNotAdjustAdmin = from u in Users
where !AdjusterItems.Any(x => x == u.Id)
&& u.UserType.Equals("Adjuster", StringComparison.InvariantCultureIgnoreCase)
select u;
var result = from u in UsersNotAdjustAdmin
join a in Adjusters
on u.Id equals a.UserId
select new AdjusterProfileStatusItem() { Adjuster = a, User = u };

How can I write a linq query for this?

I need to write following query in Linq to SQL but not sure what is the best way of doing, given it has two derived tables. Any suggestions.
SELECT A.ID
FROM
(
SELECT *
FROM Orders
WHERE ProductID = 5
) A
JOIN
(
SELECT CustomerID, MAX(Price) Price
FROM Orders
WHERE ProductID = 5
GROUP BY CustomerID
) B
ON A.CustomerID = B.CustomerID and A.Price = B.Price
var b = (
from o in db.Orders
where o.ProductID == 5
group o by o.CustomerID into og
select new {
CustomerID = og.Key
Price = Max(og.Price)
}
);
var a = (
from o in db.Orders
join p in b on new {a.CustomerID, a.Price} equals
new {b.CustomerID, b.Price}
where o.ProductID == 5
select a.ID
);
var r = a.ToString();
These two links are invaluable when forming things like this:
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
http://msdn.microsoft.com/en-us/vstudio/bb688085
Can you simplify this with LINQ, especially if you use method syntax instead of query syntax.
orders.Where(o => o.ProductID == 5)
.GroupBy(o => o.CustomerID)
.SelectMany(g => g.Where(o => o.Price == g.Max(m => m.Price)));
My advice when writing LINQ, do not simply attempt to convert a SQL statement exactly. Think about the desired result and develop a solution designed for LINQ.
Something along these lines:
var result = from a in context.Orders
join b in (context.Orders.Where(o => o.ProductID == 5).GroupBy(o => o.CustomerID).Select(g => new { CustomerID = g.Key, Price = g.Max(o => o.Price)))
on new {a.CustomerID, a.Price} equals new {b.CustomerID, b.Price}
where a.ProductID == 5
select a.ID;

Categories

Resources