Linq equivalent to a Sql Query - linq

SQL Query -
select q.QuesId, q.Title, q.Description, count(a.QuesId) as Answers
from Question q
join Answer a on q.QuesId = a.QuesId
group by q.QuesId, q.Title, q.Description
I want to convert this Sql query to linq.
My approach is -
var questions = (from q in db.Questions
join a in db.Answers on q.QuesId equals a.QuesId
group q by new
{ q.QuesId, q.Title, q.Description, q.AskedBy, q.AskedOn, q.ModifiedOn }
into x
select new
{ x.Key.QuesId, x.Key.Title, x.Key.Description, x.Key.AskedBy, x.Key.AskedOn, x.Key.ModifiedOn, x.key.Answers.count }
).ToList();
It doesn't seem to be working.

This is what I end up doing which works well for me -
var questions = db.Questions
.GroupJoin(db.Answers, q => q.QuesId, a => a.QuesId, (q, a) => q)
.GroupBy(q => new { q.QuesId })
.SelectMany(x => x.Select(q => new
{ q.QuesId, q.Title, q.Description, q.UserDetail.FirstName, q.UserDetail.LastName, q.AskedOn, q.ModifiedOn, q.Answers.Count }
)).Distinct();

Related

How to subtract the two columns sum of amount using linq

Below my query which not working properly could any one help here?
enter code here
var collectionamount = (from u in db.bank_deposit
join pr in db.collections on u.AgentID equals pr.AgentID into g
join agentname in db.agent_master on u.AgentID equals agentname.AgentID
group u by new { u.AgentID } into x
select new collectionwithdeposit
{
AgentName = agentname.AgentName,
DepositedAmount = g.Sum(m => m.DepositedAmount),
CollectionAmount = g.Sum(z => z.AmountReceived),
Balance = g.Sum(u => u.DepositedAmount) - g.Sum(v => v.AmountReceived)
}).ToList();
lstdataModel.Add(dataModel);
}
The variable g does not exists in the scope of your select. This is because of the into keyword. What you are writing is in effect..
var tempEnumerable = from u in db.bank_deposit
join pr in db.collections on u.AgentID equals pr.AgentID into g
join agentname in db.agent_master on u.AgentID equals agentname.AgentID
group u by new { u.AgentID };
var collectionamount = from x in tempEnumerable
select new collectionwithdeposit
{
AgentName = agentname.AgentName,
DepositedAmount = g.Sum(m => m.DepositedAmount),
CollectionAmount = g.Sum(z => z.AmountReceived),
Balance = g.Sum(u => u.DepositedAmount) - g.Sum(v => v.AmountReceived)
}).ToList();
The into keyword in Linq is for creating a new scope.
In fact you really don't want to use into as often as you do
Try this
var collectionAmount = from u in db.bank_deposit
where db.collections.Any(pr => pr.AgentID == u.AgentID)
join agentname in db.agent_master on u.AgentID equals agentname.AgentID
group u by agentname into g
select new collectionwithdeposit
{
AgentName = g.Key.AgentName,
DepositedAmount = g.Sum(m => m.DepositedAmount),
CollectionAmount = g.Sum(z => z.AmountReceived),
Balance = g.Sum(u => u.DepositedAmount) - g.Sum(v => v.AmountReceived)
}
EDITED:
Maybe actually what you want is this...I don't know your table structures. But I am going to assume you have no idea about Linq, and your tables are sane (since my last answer assumed the opposite).
var collectionAmount = from agent in db.agent_master
let depositedAmount = db.bank_deposit
.Where(d => d.AgentID == agent.AgentID)
.Sum(d => c.DepositedAmount)
let collectionAmount = db.collections
.Where(c => c.AgentID == agent.AgentID)
.Sum(c => c.AmountReceived)
select new collectionwithdeposit
{
AgentName = agent.AgentName,
DepositedAmount = depositedAmount,
CollectionAmount = collectionAmount,
Balance = depositedAmount - collectionAmount
}

LINQ Max Date with group by

I have a requirement to sort a list by 1) the number of times a distinct item appears and then 2) if the count of two distinct rows is the same, the most recently used date of that group.
My group by function and sorting by count is working without the date:
(from x in data
group x by new { x.Col1, x.Col2, x.Col3}
into g
let count = g.Count()
select new
{
g.Key.Col1,
g.Key.Col2,
g.Key.Col3,
count
}).OrderByDescending(x => x.count)
However, I have been unable to successfully add the date sort. I was trying to add the date column as an aggregate in the group by expression, but that doesn't work.
(from x in data
group x by new { x.Col1, x.Col2, x.Col3, MaxDate = x.CreatedDateTime.Max()}
into g
let count = g.Count()
select new
{
g.Key.Col1,
g.Key.Col2,
g.Key.Col3,
count,
g.Key.MaxDate
}).OrderByDescending(x => x.count).ThenByDescending(x => x.MaxDate)
I get why it doesn't work, I just can't think of another route to add the secondary sort. Any ideas are appreciated!
This is what you're looking for (I think)
from x in data
group x by new { x.Col1, x.Col2, x.Col3}
into g
let count = g.Count()
select new
{
g.Key.Col1,
g.Key.Col2,
g.Key.Col3,
MaxDate = g.Select(x => x.CreatedDateTime)
.OrderByDescending(d => d).FirstOrDefault(),
count
}).OrderByDescending(x => x.count).ThenByDescending(x => x.MaxDate)
How about:
var ordered = Elev8SnaTowelTables
.GroupBy(x => new { x.Col1, x.Col2, x.Col3 })
.OrderByDescending(g => g.Count())
.ThenByDescending(g => g.Max(x => x.CreatedDateTime));

Complex Linq Collection Query

I have this DB diagram and want to make a query to find all UserLists in a given region. RegionId is supplied.
So I can get all the departments by this code (may not be the best way..):
var region = context.Regions.Find(regionId);
IEnumerable<Department> departments = region.Areas
.SelectMany(a => a.Workplaces)
.SelectMany(w => w.Departments);
The Account can have many UserLists, and an Account can be linked to many Departments. Can someone formulate a queryto achieve this please?
for completeness the final code was:
List<UserList> query2 = context.Regions.Where(r => r.RegionId == regionId)
.SelectMany(r => r.Areas)
.SelectMany(a => a.Workplaces)
.SelectMany(w => w.Departments)
.SelectMany(d => d.AccountsAllowedToPost)
.Distinct()
.SelectMany(da => da.Lists).ToList();
You can use the let syntax (or the .Select method) to navigate the ManyToOne relationship.
var query =
from r in context.Regions
where r.RegionId == regionId
from a in r.Areas
from w in a.Workplaces
from d in w.Departments
from da in d.DepartmentAccounts
let acc = da.Account
from u in acc.UserLists
select u;
var query2 = context.Regions.Where(r => r.RegionId == regionId)
.SelectMany(r => r.Areas)
.SelectMany(a => a.Workplaces)
.SelectMany(w => w.Departments)
.SelectMany(d => d.DepartmentAccounts)
.Select(da => da.Account)
.SelectMany(acc => acc.UserLists);

LINQ 2 lefts joins with Sum

I am trying to do a relatively straight forward SQL query with linq:
SELECT ir.resource_id, r.first_name, r.surname, rt.job_title, SUM(plan_ts_hours), SUM(ts_hours) FROM tbl_initiative_resource ir
INNER JOIN tbl_resource r ON ir.resource_id = r.resource_id
INNER JOIN tbl_resource_type rt ON rt.resource_type_id = r.resource_type_id
LEFT JOIN tbl_plan_timesheet pts on pts.resource_id = ir.resource_id AND pts.initiative_id = ir.initiative_id
LEFT JOIN tbl_timesheet ts on ts.resource_id = ir.resource_id AND ts.initiative_id = ir.initiative_id
WHERE ir.initiative_id = 111
GROUP BY ir.resource_id, r.first_name, r.surname, rt.job_title
After reading this blog: http://smehrozalam.wordpress.com/2010/04/06/linq-how-to-build-complex-queries-utilizing-deferred-execution-and-anonymous-types/
I came up with the following linq:
var query = (from initRes in Context.tbl_initiative_resource
join res in Context.tbl_resource on initRes.resource_id equals res.resource_id
join resType in Context.tbl_resource_type on res.resource_type_id equals resType.resource_type_id
from tsheet in Context.tbl_timesheet.Where(x => x.resource_id == initRes.resource_id).Where(x => x.initiative_id == initRes.initiative_id).DefaultIfEmpty()
from plannedtsheet in Context.tbl_plan_timesheet.Where(x => x.resource_id == initRes.resource_id).Where(x => x.initiative_id == initRes.initiative_id).DefaultIfEmpty()
where initRes.initiative_id == initiativeID
group new { ID = res.resource_id, ResourceType = resType.job_title, Times = tsheet, P = plannedtsheet } by initRes.resource_id into g
select new
{
ResourceID = g.Key,
Hours = g.Sum(x => (decimal?)x.Times.ts_hours),
PlannedHours = g.Sum(x => (decimal?)x.P.plan_ts_hours)
}).ToList();
Any ideas on how I can access the ResourceType when selecting the new anonymous type?
ResourceType is part of the the grouping key, so g.Key.ResourceType should do it.
(Check out the type of ResouceID in the results, as you've assigned it g.Key it will be an instance of the (anonymous) type created in the group clause.

Convert Linq Query Expression to Method Syntax equivalent

I use LINQ, C#, EF4.
I have this query expression in Linq. I need to convert in a equivalent in Method Syntax but I have some doubt on the struction. Could you provide me a good example. Thanks for your help.
var myContentsForAuthor = from c in context.CmsContents
join a in context.CmsAuthors on c.AuthorId equals a.AuthorId
join u in context.aspnet_Users on a.UserId equals u.UserId
orderby c.Title ascending
where u.UserId == myUserGuid && c.IsDeleted == false && c.Title.Contains(nameSearchString)
select c;
Well, this gets complicated because of the transparent identifiers, but something like:
var myContentsForAuthor = context.CmsContents
.Join(context.CmsAuthors,
c => c.AuthorId
a => a.AuthorId,
(c, a) => new { c, a })
.Join(context.aspnet_Users,
z => z.a.UserId,
u => u.UserId,
(z, u) => new { z, u })
.OrderBy(zz => zz.z.c.Title)
.Where(zz => zz.u.UserId == myUserGuid &&
zz.z.c.IsDeleted == false &&
zz.z.c.Title.Contains(nameSearch))
.Select(zz => zz.z.c);

Resources