linq groupby question - c#

I have a table that has several columns: HarvestID, HarvestDate, UserID to mention the main ones.
For each date, there are going to be several HarvestID per day.
So far, I have the following linq query:
TheUserID and TheMonth are passed in as an int and a DateTime
var MyQuery = from h in MyDC.HarvestTable
where h.UserID == TheUserID
where h.HarvestDate.Month == TheMonth.Month
where h.HarvestDate.Year == TheMonth.Year
group h by h.HarvestDate.Day into TheDays
from d in TheDays
select new
{
TheDay = d.HarvestDate.Date,
TheDayCount = (from c in TheDay
select c.HarvestID).Count()
};
I'm looking to have the output be a list of counts per day. The query doesn't bug but the problem is that at the moment the query is not returning a unique row for each day. The grouping doesn't work and I'm not finding out why. What's wrong with this code?
Thanks.

It think your query should be
var MyQuery = from h in MyDC.HarvestTable
where h.UserID == TheUserID
where h.HarvestDate.Month == TheMonth.Month
where h.HarvestDate.Year == TheMonth.Year
group h by h.HarvestDate.Day into TheDays
select new
{
TheDay = TheDays.Key,
TheDayCount = TheDays.Count()
};
Here is a vry good refrence to above group by statement http://msdn.microsoft.com/en-us/vcsharp/aa336754.aspx#simple1

var MyQuery = from h in MyDC.HarvestTable
where h.UserID == TheUserID
&& h.HarvestDate.Month == TheMonth.Month
&& h.HarvestDate.Year == TheMonth.Year
group h by h.HarvestDate.Day into g
select new
{
TheDay = g.Key,
TheDayCount = g.Count()
};
This will not give you zeroes on the days where there is no data - but should give you a count where there is.
http://msdn.microsoft.com/en-us/vcsharp/aa336746 is my go-to page for LINQ examples.

Related

Convert sql query to linq in C#

Hi Could any one help how to write this below query in Linq C#
select YearValue from [Information].Year
where YearId in (select max(YearId) from curreny where BudgetCodeId = 2)
Here's what I've tried:
var maxYear =
from year in dbContext.Years
join exchange in dbContext.CurrencyExchangeRates
on year.YearId equals exchange.YearId
where exchange.BudgetCodeId == budgetCodeId
orderby year.YearValue descending
select new { yearValue = year.YearValue };
This is what you're looking for:
var maxYear = from year in dbContext.Years where (from exchange in dbContext.CurrencyExchangeRates where exchange.BudgetCodeId == 2 select exchange)
.Max(m => m.YearId) ==
year.YearId select year.YearValue;
int mYear = maxYear.First();

LINQ to SQL ,Join tables to get distinct result?

I am trying to write a LINQ query that will get me some distinct values from two SQL Server data tables.
I have two tables named, Facility_Cost_TBL and Tenant_Bills_TBL.
I then have a column that is named Nursing_Home_Name which I am trying to get the distinct data from.
This is my effort in LINQ , however it does not work,
var name = (from f in dataContext.Facility_Cost_TBLs
join t in dataContext.Tenant_Bills_TBLs on f.Tenant_Code equals t.Tenant_Code
where f.Tenant_Code == code && f.Date_Month == date.Month && f.Date_Year == date.Year
select new {Facility_Cost_TBL = f, Tenant_Bills_TBL = t}).Distinct();
And this is a working SQL statement I made that does what I want via T-SQL.
SELECT DISTINCT Nursing_Home_Name
FROM (SELECT Nursing_Home_Name
FROM Facility_Cost_TBL
WHERE Date_Year = 2016 AND Date_Month = 10 AND Tenant_Code = 664250
UNION SELECT Nursing_Home_Name
FROM Tenant_Bills_TBL
WHERE Year_Data = 2016 AND Month_Data = 10 AND Tenant_Code = 664250)
a
Could someone show me what LINQ sytax AND what LINQ extension method query would look like?
Please try following
var names = ((from f in dataContext.Facility_Cost_TBLs
where f.Tenant_Code == "664250" && f.Date_Month == "10" && f.Date_Year == "2016"
select new { Nursing_Home_Name = f.Nursing_Home_Name }).
Union(
from t in dataContext.Tenant_Bills_TBLs
where t.Tenant_Code == "664250" && t.Date_Month == "10" && t.Date_Year == "2016"
select new { Nursing_Home_Name = t.Nursing_Home_Name })).ToList();
Hope this will help you
Try this to see if this works. LINQ to SQL: Multiple joins ON multiple Columns. Is this possible?
var name = (from f in dataContext.Facility_Cost_TBLs
join t in dataContext.Tenant_Bills_TBLs equals on new { f.Tenant_Code, f.Date_Month, f.Date_Year } equals new { t.Tenant_Code, t.Date_Month, t.Date_Year }
where f.Tenant_Code == code && f.Date_Month == date.Month && f.Date_Year == date.Year
select new {Facility_Cost_TBL = f, Tenant_Bills_TBL = t}).Distinct();

LINQ SELECT TAKE 1 EACH ROW

How can i select take 1 each data in column in linq that only return 1 row. Because when i put .Take(1) only 1 row result will appear but i want to have 2 row result with different entry
to make it clear here's what i mean
in c# here's my query
using (PharmacyDBEntities entities = new PharmacyDBEntities())
{
var positem = (from a in entities.POSEntries.Take(1)
where a.Invoice.AccountID == authLogin.userid && a.Invoice.InvoiceStatusID == 1
select new
{
a.Item.ItemCode,
a.Item.Name,
Quantity = (from b in entities.POSEntries where b.Invoice.AccountID == authLogin.userid && b.Invoice.InvoiceStatusID == 1 select b).Count(),
a.Item.SellingPrice
}).ToList();
gcItemList.DataSource = positem;
}
And the result
Is there any suggestion guys? will make big help to me. thanks
You can use Linq GroupBy
var positem = entities.POSEntries.Where( a=> a.Invoice.AccountID == authLogin.userid && a.Invoice.InvoiceStatusID == 1)
.GroupBy(x=>x.Item.ItemCode).Select(g=> new {
g.Key,
g.First().Item.Name,
Quantity = g.Count(),
g.First().Item.SellingPrice
}).ToList();
So, you want Distinct() instead of Take(1)? Something along these lines:
var positem = (from a in entities.POSEntries
where a.Invoice.AccountID == authLogin.userid && a.Invoice.InvoiceStatusID == 1
select new
{
a.Item.ItemCode,
a.Item.Name,
Quantity = (from b in entities.POSEntries where b.Invoice.AccountID == authLogin.userid && b.Invoice.InvoiceStatusID == 1 select b).Count(),
a.Item.SellingPrice
}).Distinct().ToList();
Take only returns first n elements. I think you need to try using the Distinct method.

how to use Linq " NOT IN"

I'm using Entity Framework
So I want to write a sql command using two tables - tblContractor and tbSiteByCont tables.
It looks like this in SQL
SELECT PKConID, Fname, Lname
FROM tblContractor
WHERE (PKConID NOT IN
(SELECT FKConID
FROM tbSiteByCont
WHERE (FKSiteID = 13)))
but I don't know how to write in Linq.
I tried like this
var query1 = from s in db.tblSiteByConts
where s.FKSiteID == id
select s.FKConID;
var query = from c in db.tblContractors
where c.PKConID != query1.Any()
select Contractor;
But this doesn't work.
So how should I write it? What is the procedure? I'm new to Linq.
var _result = from a in tblContractor
where !(from b in tbSiteByCont
where FKSiteID == 13
select b.FKConID)
.Contains(a.PKConID)
select a;
or
var siteLst = tbSiteByCont.Where(y => y.FKSiteID == 13)
.Select(x => x.FKConID);
var _result = tblContractor.Where(x => !siteLst.Contains(x.PKConID));
I'd use a HashSet, it ensures you only evaluate the sequence once.
var result = from p in tblContractor
let hasht = new HashSet<int>((from b in tbSiteByCont
where b.FKSiteID == 13
select b.PKConID).Distinct())
where !hasht.Contains(p.PKConID)
select p;
may this work too
var _result = from a in tblContractor
.Where(c => tbSiteByCont
.Count(sbc => sbc.FKSiteID == 13 && c.PKConID == sbc.FKConID) == 0)

Help creating a LINQ to SQL query

I'm populating a FormView by setting the datasource to an IQueryable object that I get by doing a LINQ query. Basically it returns the number of employees that hold a certain "Position" within a certain "Shift".
int shiftID = 1;
var shiftCount = from x in context.Employees.Take(1)
select new
{
ManagerCount = ((from p in context.Persons
where p.PositionID == 1 && p.ShiftID == shiftID && p.IsEmployee == true
select p.PersonId).Count(),
PartTimeCount = ((from p in context.Persons
where (p.PositionID == 2 || p.PositionID == 3) && p.ShiftID == shiftID && p.IsEmployee == true
select p.PersonId).Count(),
etc, etc...
};
That part works fine. However, when I want to get the number of employees for all shifts, I can't quite figure out how to do it:
//Get all shifts 1, 2, and 3
var shiftCount = from x in context.Employees.Take(1)
select new
{
ManagerCount = ((from p in context.Persons
where p.PositionID == 1 && (p.ShiftID == 1 || p.ShiftID == 2 || p.ShiftID == 3) && p.IsEmployee == true
select p.PersonId).Count()
};
That doesn't work though because it of course returns 3 values and gives the Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. error.
So I need to get the sum of the three values returned (it's not always three though, it depends on the position).
I've looked at various ways using Sum and LINQ grouping, but can't quite seem to work it out. Can anybody point me in the right direction?
I've got a few answers for you, but first it seems like you have something wrong with your first part of your query. You're doing .Take(1) on Employees which will give you only one x value. Since you don't use x in the remainder of your query then using Employees is redundant.
Now, since all of your queries are quite similar I've tried to remove repetition. The first thing to do is to get a common filter for the shifts you are filtering on.
If you have a single shift, use this:
int shiftID = 1;
var shifts = new [] { shiftID, };
If you have multiple shifts, use this:
var shifts = new [] { 1, 2, 3, };
Either way you end up with an array of integers representing the shifts you want to filter against. All of the below answers require this shifts array.
Then define a query for the employees in those shift, regardless of position for now.
var employeesInShifts =
from p in context.Persons
where p.IsEmployee
where shifts.Contains(p.ShiftID)
select p;
So you can then get the shift counts like so:
var shiftCount =
new
{
ManagerCount = employeesInShifts
.Where(p => p.PositionID == 1)
.Count(),
PartTimeCount = employeesInShifts
.Where(p => p.PositionID == 2 || p.PositionID == 3)
.Count(),
// etc
};
Perhaps a better alternative for you though, would be to turn the employeesInShifts query into a dictionary and then just pluck the values from the dictionary.
var employeesInShifts =
(from p in context.Persons
where p.IsEmployee
where shifts.Contains(p.ShiftID)
group p by p.PositionID into gps
select new
{
PositionID = gps.Key,
Count = gps.Count(),
})
.ToDictionary(pc => pc.PositionID, pc.Count);
var shiftCount =
new
{
ManagerCount = employeesInShifts[1],
PartTimeCount = employeesInShifts[2] + employeesInShifts[3],
// etc
};
The downside to this approach is that you really should check that the dictionary has values for each PositionID before getting the values.
That can be fixed by introducing an array of position ids that you want the dictionary to have and joining your results on that.
var positionIDs = new [] { 1, 2, 3, };
var employeesInShifts =
(from p in context.Persons
where p.IsEmployee
where shifts.Contains(p.ShiftID)
where positionIDs.Contains(p.PositionID)
select p).ToArray();
var allPositionEmployeesInShifts =
from pid in positionIDs
join p in employeesInShifts on pid equals p.PersonId into gps
select new
{
PositionID = pid,
Count = gps.Count(),
};
var countOfPositionID =
allPositionEmployeesInShifts
.ToDictionary(x => x.PositionID, x => x.Count);
var shiftCount =
new
{
ManagerCount = countOfPositionID[1],
PartTimeCount = countOfPositionID[2] + countOfPositionID[3],
// etc
};
Now that guarantees that your final dictionary will contain the counts of all of the position ids that you are wanting to query.
Let me know if this works or if you really needed to join on the Employees table, etc.
I would recommend looking at the Group By examples here:

Categories