How to total quantity based on date range from another table? - c#

how to total quantity based on date range from another table?
var items = entity.ItemHeaders.Where(x => x.date >= _dateFrom && x.date <= dateTo);
var tQty = entity.ItemContents.Where(x => x.Warehouse == dto.Warehouse).Sum(x => x.Quantity);
the problem is I don't have any idea how to connect them.

To join the entity by HeaderNumber and sum the total:
var total = (from header in entity.ItemHeaders
from content in entity.ItemContents
where header.date >= _dateFrom && header.date <= dateTo
&& content.Warehouse == dto.Warehouse
&& header.ID = content.HeaderNumber
select content.Quantity).Sum();
Assuming you are using Entity Framework, it will be easier if you have a Navigation Property defined in ItemContent for the ItemHeader. e.g.:
public virtual ItemHeader Header {get; set;}
Then the query could be:
var total = entity.ItemContents
.Where(x=> x.Header.date >= _dateFrom && x.Header.date <= dateTo
&& x.Warehouse == dto.Warehouse)
.Sum(x => x.Quantity);

Related

Adding Summed columns together using Linq

I am wondering if there is an easier way of adding together summed columns inside a group by query using Linq. I am wanting to check wether column1 + column2 is greater than 2250, and if so do something...
Below is a snippet of code im using, a much slimmed down version for use here
from contact in _db.Worksheets
join person in _db.MyTable on contact.Email equals
person.EmailAddress
orderby contact.ShiftDate ascending
select new
{
EmployeeNumber = person.EmployeeNumber,
Overtime1= contact.Overtime1,
Overtime2= contact.Overtime2,
ShiftDate = contact.ShiftDate,
} into t1
group t1 by t1.EmployeeNumber into pg
select (new
{
OvertimeTotal = pg.Sum(x => x.ShiftDate >= vStart1 && x.ShiftDate <= vEnd1 ? x.Overtime1 : 0)
+ pg.Sum(x => x.ShiftDate >= vStart1 && x.ShiftDate <= vEnd1 ? x.Overtime2 : 0) > 2250 (....then do something)
I was wondering if you could do something like the below. (Which I have tried and it doesnt work)
I am using entity framework too, so realise there may be complications converting this type of query
OvertimeTotal = pg.Sum(x => x.ShiftDate >= vStart1 && x.ShiftDate <= vEnd1 ? x.Overtime1 + x.Overtime2 : 0)
It would help if you specify what you want when there is overtime. The following will return the employee numbers with overtime.
The approach is a little different from yours, as it filters the worksheet records before joining with the person records for optimization reasons. It then filters to just the employees that have overtime.
I'm assuming an employee has overtime if overtime1 + overtime2 of all their shifts in the specified date range adds up to more than 2250.
var employeesWithOvertime = _db.Worksheets
.Where(w => w.ShiftDate >= vStart1 && w.ShiftDate <= vEnd1)
.Join(_db.MyTable, w => w.Email, p => p.EmailAddress, (w, p) => new
{
EmployeeNumber = p.EmployeeNumber,
Overtime1 = w.Overtime1,
Overtime2 = w.Overtime2
})
.GroupBy(x => x.EmployeeNumber)
.Select(g => new
{
EmployeeNumber = g.Key,
OvertimeTotal = g.Sum(x => x.Overtime1 + x.Overtime2)
})
.Where(x => x.OvertimeTotal > 2250);

Linq - Dynamic Condition

I have the following query :-
I want to add one more condition which is dynamic, so if user passes DATEOFBIRTH it should be e.DateOfBirth <= date.
var data = ctx.Employee.Where(e => e.Id == Id
&& e.Category == Category
&& e.DateOfJoining <= date)
.Select(e => e)
.ToList();
How to condition dynamically?
You can use reflection to solve this problem but there is another idea that may helps you:
var criteria = new Dictionary<string, Func<Employee, bool>>();
var date = DateTime.Now; //or any other value
//Initialize your criterias
criteria.Add("DATEOFBIRTH", e => e.DateOfBirth <= date);
criteria.Add("DateOfJoining", e => e.DateOfJoining <= date);
var selectedValue = "DATEOFBIRTH";
var data = ctx.Employee.Where(e => e.Id == id &&
e.Category == Category &&
criteria[selectedValue](e)).ToList();
So if you change the selectedValue the output will be based on corresponding criteria you are looking for.
From your comment:
If the DateOfBirth is choosen, there where condition should be appended
by one more condition e.DateOfBirth <= date.. if user chooses
DateOfAnniversary then it should be e.DateOfAnniversary <= date
Then you could use:
var data = ctx.Employee
.Where(e => e.Id == Id && e.Category == Category && e.DateOfJoining <= date);
Now, assuming that filterbyDateOfBirth and filterbyDateOfAnniversary are bools:
if(filterbyDateOfBirth)
data = data.Where(e => e.DateOfBirth <= date);
if(filterbyDateOfAnniversary)
data = data.Where(e => e.DateOfAnniversary <= date);
var list = data.ToList();
Due to LINQ's deferred execution the database is queried just once at ToList.
Sounds like you're trying to do the following:
var employees = ctx.Employee.Where(e => e.Id == Id
&& e.Category == Category
&& e.DateOfJoining <= date);
if (!string.IsNullOrWhiteSpace(DATEOFBIRTH))
{
employees = employees.Where(e => e.DateOfBirth <= DATEOFBIRTH);
}
var data = employees.ToList();
You could also do the following, which is more concise, but since it looks like you are querying a database here, I would prefer the above approach since it doesn't include anything unnecessary in the query.
var data = ctx.Employee.Where(e => e.Id == Id &&
e.Category == Category &&
e.DateOfJoining <= date &&
(string.IsNullOrWhiteSpace(DATEOFBIRTH) ||
e.DateOfBirth <= DATEOFBIRTH))
.ToList();

how to show result using multiple Order by descending using linq query

I am having 3 criteria. I want to order these 3 types.
Who Paid with Master User
Who Update their Post Latest Date
Who Paid with Sub Master User
which one is having count it will come to top 15 Jobs.
My code here:
var orderMaster= _vasRepository.GetOrderDetails()
.Where(od => od.OrderMaster.OrganizationId != null &&
od.OrderId == od.OrderMaster.OrderId &&
od.OrderMaster.PaymentStatus == true &&
od.ValidityTill.Value >= currentdate)
.OrderByDescending(od => od.ValidityTill)
.Select(ord => ord.OrderMaster.Id.Value);
var updatedVacancyList = _repository.GetJobs()
.Where(c => c.UpdatedDate != null &&
updateFresh <= c.UpdatedDate)
.Select(c => c.Id);
var orderLatestUser = _vasRepository.GetOrderDetails()
.Where(od => od.OrderMaster.UserId != null &&
od.OrderMaster.PaymentStatus == true &&
freshUser <= od.ActivationDate &&
od.ValidityTill.Value >= currentdate)
.Select(c => c.OrderMaster.User.Id);
Then I check the count of those then assign to
List<int> lstMasterId = orderOrganization.ToList();
List<int>lstUpdatedJobsListId = updatedVacancyList.ToList();
List<int>lstUserListId= orderLatestUser.ToList();
Here i order the lists using query
Func<IQueryable<Job>, IOrderedQueryable<Job>> orderingFunc = query =>
{
if (orderMaster.Count() > 0)
return query.OrderByDescending(rslt =>
lstOrganizationId.Contains(rslt.OrganizationId))
.ThenByDescending(rslt=>lstUserListId.Contains(rslt.User.Id))
.ThenByDescending(rslt => lstUpdatedJobsListId.Contains(rslt.Id))
.ThenByDescending(rslt => rslt.CreatedDate);
else
return query.OrderByDescending(rslt => rslt.CreatedDate);
};
jobs = orderingFunc(jobs);
}
I want to show the lstUserListId at top of the result.. How to do this?

Left Outer Calendar Table Join with LINQ-to-SQL

How can I write the following LEFT OUTER JOIN SQL query against my Calendar and Sales tables for the purpose of grouping summed sales by day, week or month in LINQ so that it can be materialised by LINQ-to-SQL?
SELECT c.CalendarDate, c.FirstDayOfWeek, c.FirstDayOfMonth,
ISNULL(s.Total, 0) as Total
FROM Calendar as c
LEFT OUTER JOIN Sales as s
on s.SaleDate >= c.CalendarDateTime and
s.SaleDate < c.NextDayDateTime
WHERE s.SaleDate BETWEEN #since and #until
I managed to get an inner join working in LINQ, but I need an outer join to retrieve days with zero sales. Here is the code I use for an inner join:
var sales = from s in db.Sales
from c in db.Calendars
where
s.SaleDate >= c.CalendarDate && s.SaleDate < c.NextDayDateTime
&& s.SaleDate >= sinceDate && s.SaleDate < dateEnd
select new
{
c.CalendarDate,
c.FirstDateOfWeek,
c.FirstDateOfMonth,
s.Total
};
I can then switch on a date interval and group sales as follows:
Daily:
var groupedSales = sales.GroupBy(x => x.CalendarDate);
Weekly:
var groupedSales = sales.GroupBy(x => x.FirstDateOfWeek);
Monthly:
var groupedSales = sales.GroupBy(x => x.FirstDateOfMonth);
Finally:
var salesReport = from g in groupedSales
orderby g.Key
select new {
Date = g.Key,
Total = g.Sum(x => x.Total)
};
Alternatively, it could also work to inject zero sale records into my report after retrieving sales for non-zero days only.
What about this?
var sales = from s in db.Sales
from c in db.Calendars.DefaultIfEmpty()
where
s.SaleDate >= c.CalendarDate && s.SaleDate < c.NextDayDateTime
&& s.SaleDate >= sinceDate && s.SaleDate < dateEnd
EDIT:
You can create helper classes like this:
class CalendarSealesHelper
{
public DateTime CalendarDate {get; set;}
public DateTime NextDayDateTime {get; set;}
}
class CalendarSealesHelperComparer : IEqualityComparer<CalendarSealesHelper>
{
public bool Equals(CalendarSealesHelper c1, CalendarSealesHelper c2)
{
if (c2.CalendarDate >= c1.CalendarDate
&& c2.NextDayDateTime < c1.NextDayDateTime)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(CalendarSealesHelper c)
{
int hCode = (int)c.CalendarDate.Ticks ^ (int)c.NextDayDateTime.Ticks;
return hCode.GetHashCode();
}
}
Then try this:
var query = db.Calendars.GroupJoin(
db.Sales,
c => new CalendarSealesHelper{c.CalendarDate, c.NextDayDateTime},
s => new CalendarSealesHelper{s.SaleDate, s.SaleDate},
(c, s) => new {Calendars = c, Sales = s},
new CalendarSealesHelperComparer())
.SelectMany(s => s.Sales.DefaultIfEmpty(),
(c, s) => new {
CalendarDate = c.CalendarDate,
FirstDayOfWeek = c.FirstDayOfWeek,
FirstDayOfMonth = c.FirstDayOfMonth,
Total = s.Total,
SaleDate = s.SaleDate
})
.Where(r => r.SaleDate >= sinceDate && r.SaleDate <= dateEnd);

Date range overlap issue in LINQ

Given date range in Table for particular record say for particular feild "Name"
If some one trying to insert that Name within previous date range interval then it should not be allowed.
I have tried here some code look at this ...
if (dataContext.TableAs.Where(
x => x.EndDate > StartDate &&
x.Name == Name).Count() == 0)
{
//insert record
}
but is not successful all times.
Can anyone suggest what I have missing over here ?
I have tried below query in SQL , how can I use that in LINQ for above code
SELECT COUNT(*) FROM TableA WHERE ('2012-04-02' between StartDate and EndDate or '2012-08-28'
between StartDate and EndDate or StartDate between '2012-04-02' and '2012-08-28' or EndDatebetween '2012-04-02' and '2012-08-28' ) and Name='Test'
try this;
if (dataContext.TableAs
.Where(x => x.Name == Name)
.Max(x => x.EndDate) < StartDate)
EDIT - For second part of question
DateTime Date1 = new DateTime("2012-04-02");
DateTime Date2 = new DateTime("2012-08-28");
var query = (dataContext.TableAs
.Where(x => x.Name == "Test")
.Where(x => (x.StartDate >= Date1 && Date1 <= x.EndDate)
|| (x.StartDate >= Date2 && Date2 <= x.EndDate)
|| (Date1 >= x.StartDate && x.StartDate <= Date2)
|| (Date1 >= x.EndDate && x.EndDate <= Date2))).Count();
var StartDate = new DateTime(2012,04,02);
var EndDate = new DateTime(2012,08,28);
var Name = "Test";
if (!dataContext.TableAs.Any(
x=> x.Name == Name && x.EndDate >= StartDate && x.StartDate <= EndDate
)
{
//insert record
}

Categories

Resources