I have the following SQL query to be translated to LINQ
string qWhere;
DateTime startDate = DateTime.Parse("2018-02-01");
DateTime endDate = DateTime.Parse("2018-02-03");
if(manual == true)
{
qWhere = " deliveryDate>=" + startDate + " and deliveryDate<=" + endDate;
}
else
{
qWhere = "deliveryDate>=" + DateTime.Now;
}
string sqlQuery = "select * from LoadingOrder where " + qWhere;
can anyone help me to translate this query to LINQ, table LoadingOrder have million rows.
Many thanks
If it was just the one condition then you could have two separate queries instead of one query. I think that's a lot easier to read and follow then placing the conditional inside the query itself.
var now = DateTime.Now;
if(manual)
result = LoadingOrders.Where(s=> s.deliveryDate >= startDate && s.deliveryDate <= endDate);
else
result = LoadingOrders.Where(s=> s.deliveryDate >= now);
Suppose the query has lots of conditions and the "delivery date" condition is the only one that changes. In that case you probably wouldn't want to have two entire versions of the query with just one difference. In that case, you can create that one condition separately.
To do that you would create a Func<LoadingOrder, bool> - a function that takes a LoadingOrder and returns true or false. And then you would assign whichever condition you want to check for to that function.
Func<LoadingOrder, bool> deliveryDateCondition;
if(manual)
deliveryDateCondition = loadingOrder =>
loadingOrder.deliveryDate >= startDate && loadingOrder.deliveryDate <= endDate;
else
{
var now = DateTime.Now;
deliveryDateCondition = loadingOrder => loadingOrder.deliveryDate >= now;
}
Now deliveryDateCondition is function that takes a LoadingOrder and returns true or false. You can add that function into your LINQ query, and it works regardless of which function was selected.
var result = LoadingOrders.Where(loadingOrder => deliveryDateCondition(loadingOrder)
&& ...some other condition...
&& ...some other condition...);
Something like this:
DateTime startDate = DateTime.Parse("2018-02-01");
DateTime endDate = DateTime.Parse("2018-02-03");
bool manual = ...;
loadingOrders.Where(
o => o.DeliveryDate >= startDate &&
o.DeliveryDate <= endDate &&
manual ||
o.DeliveryDate >= DateTime.Now &&
!manual);
var now = DateTime.Now;
var query = from e in db.LoadingOrder
where (e.deliveryDate >= startDate && e.deliveryDate <= endDate && manual)
|| (e.deliveryDate >= now)
select e;
OR
var query = db.LoadingOrder.Where(x => (x.deliveryDate >= startDate && x.deliveryDate <= endDate && manual) || (x.deliveryDate >= now));
Related
Check the CountEmailChart carefully. Here I am taking input of DateTime which is fully formatted date with time. But the problem is I want to compare only the date, not time, on Entity Framework below to count number of rows. Can anyone tell me how I can do this?
Controller code:
public int CountEmailChart(DateTime date, int campaignID)
{
int count = dbcontext.CampaignEmails
.Count(x => x.DateSigned == date && x.CampaignID == campaignID);
return count;
}
Karan's answer is correct but resulting query won't use an index for DateSigned. If a such index exist (or combined index for CampaignID and DateSigned columns) you may prefer this approach:
var startDate = date.Date;
var endDate = date.Date.AddDay(1);
int count = dbcontext.CampaignEmails.Count(x => x.CampaignID == campaignID && x.DateSigned >= startDate && x.DateSigned < endDate);
Try like this. .Date property on DateTime object will return only Date part.
If you are using Entity Framework 6 then.
date = date.Date;
int count = dbcontext.CampaignEmails.Count(x => DbFunctions.TruncateTime(x.DateSigned) == date.Date && x.CampaignID == campaignID);
Else
date = date.Date;
int count = dbcontext.CampaignEmails.Count(x => EntityFunctions.TruncateTime(x.DateSigned) == date.Date && x.CampaignID == campaignID);
I have a table contain the payment records of agencies. I want to sum total payment of each agency into 2 columns, first is current day payment and second is the day before payment.
So I try the SQL like this.
select p1.UserName, p1.PaymentAmount, p2.PaymentAmount
from vw_Agency_Payment p1
join vw_Agency_Payment p2 on p1.UserName=p2.UserName
where p1.PaymentDate = '2014-08-07'
and p2.PaymentDate = '2014-08-08'
It is successful and return the data.
But when I convert it to Linq like below:
var yesterday = DateTime.Today.AddDays(-1);
var tomorrow = DateTime.Today.AddDays(1);
var agencyPayment = from y in db2.vw_Agency_Payment
join t in db2.vw_Agency_Payment on y.UserName equals t.UserName
where y.PaymentDate >= yesterday
&& y.PaymentDate < DateTime.Today
&& t.PaymentDate >= DateTime.Today
&& t.PaymentDate < tomorrow
select new AgencyPaymentModel
{
agencyUserCode = y.UserName,
yesterdayPayment = y.PaymentAmount,
todayPayment = t.PaymentAmount,
growth = (t.PaymentAmount - y.PaymentAmount) / y.PaymentAmount * 100
};
return View(agencyPayment.OrderByDescending(c => c.growth).Take(100).ToList());
It return no data.
I don't know what make it wrong!?
Why not the following code (taking the date part of datetime field)?
var yesterday = DateTime.Today.AddDays(-1);
var agencyPayment = from y in db2.vw_Agency_Payment
join t in db2.vw_Agency_Payment on y.UserName equals t.UserName
where y.PaymentDate.Date = yesterday
&& t.PaymentDate.Date = DateTime.Today
select new AgencyPaymentModel
{
agencyUserCode = y.UserName,
yesterdayPayment = y.PaymentAmount,
todayPayment = t.PaymentAmount,
growth = (t.PaymentAmount - y.PaymentAmount) / y.PaymentAmount * 100
};
return View(agencyPayment.OrderByDescending(c => c.growth).Take(100).ToList());
where y.PaymentDate >= yesterday
&& y.PaymentDate < DateTime.Today
&& t.PaymentDate >= DateTime.Today
&& t.PaymentDate < tomorrow
No result will satisfy this condition:
from line 1-2, PaymentDate is limited to yesterday... intersect with line 3 will narrow down to nothing.
Basically you need to draw a reasonable range.
Plus, snippet 2 contains more logic than snippet 1, you should test them under same conditions.
I am trying to compare date only. The value in table is DateTime with format
2014-01-29 09:00:00.000. Please advise thank you
public static List<vwReportDate> GetDetail(string startDate, string endDate)
{
startDate = "2014-01-28";
endDate = "2014-01-28";
DateTime dtStart = Convert.ToDateTime(startDate);
DateTime dtEndDate = Convert.ToDateTime(endDate);
var entities = new DataEntiies();
var query = from c in entities.vwReportDate
where c.EventCreateDate >= dtStart && c.EventCreateDate <= dtEndDate
select c;
return query.ToList();
}
It looks like you're using Entity Framework and LINQ to EF. If that's true you can't use DateTime.Date property because it's not supported in LINQ to EF. You have to use EntityFunctions.TruncateTime(myDateTime) static method instead:
var query = from c in entities.vwReportDate
let eventDate = EntityFunctions.TruncateTime(c.EventCreateDate)
where eventDate >= dtStart && eventDate <= dtEndDate
select c;
My approach to this problem, which does not depend on EF, is to use "less than" for the end of the date range (after moving the end of the date range one day forward):
startDate = "2014-01-28";
endDate = "2014-01-28";
DateTime dtStart = Convert.ToDateTime(startDate);
DateTime dtEndDate = Convert.ToDateTime(endDate).AddDays(1);
var entities = new DataEntiies();
var query = from c in entities.vwReportDate
where c.EventCreateDate >= dtStart && c.EventCreateDate < dtEndDate
select c;
return query.ToList();
Question: why do you ignore the argument values provided by the method's caller?
Use the Date property of a DateTime struct to retrieve the "date" part.
Gets the date component of this instance.
Use it in code:
var query = from c in entities.vwReportDate
where c.EventCreateDate.Date >= dtStart && c.EventCreateDate.Date <= dtEndDate
select c;
If you are using Entity framework (as it looks like you do), you'll have to use the EntityFunctions.TruncateTime (helper) method, because otherwise the query can't be converted.
var query = from c in entities.vwReportDate
where EntityFunctions.TruncateTime(c.EventCreateDate) >= dtStart && EntityFunctions.TruncateTime(c.EventCreateDate) <= dtEndDate
select c;
I have the following controller code that returns a Json list object to my view that draws a pie chart.
There are 4 input parameters and i have it working with 3 of them.
However, the fist parameter entitled 'SiteTypeId' needs to be included in the where.
My problem is how to include this neatly in the code, i'd like to avoid an override of the function.
The required additional logic is:
if SiteTypeId = -1 (then this means show all so nothing is to be changed)
if SiteTypeId = 0 (then i.SiteTypeId == 0 needs to be added)
if SiteTypeId = 1 (then i.SiteTypeId == 1 needs to be added)
If 2 and 3 above were all that was required it would be easy I guess. I'm thinking there must be a neat expression for this or a neat way of splitting the LINQ into 2 with a condition perhaps.
I'm new to LINQ - can anyone advise me, here is the controller code i need to modify:
public JsonResult GetChartData_IncidentsBySiteStatus(string SiteTypeId, string searchTextSite, string StartDate, string EndDate)
{
if (searchTextSite == null)
searchTextSite = "";
DateTime startDate = DateTime.Parse(StartDate);
DateTime endDate = DateTime.Parse(EndDate);
var qry = from s in _db.Sites
join i in _db.Incidents on s.SiteId equals i.SiteId
where s.SiteDescription.Contains(searchTextSite)
&& (i.Entered >= startDate && i.Entered <= endDate)
group s by s.SiteStatus.SiteStatusDescription + "[" + s.SiteTypeId.ToString() + "]"
into grp
select new
{
Site = grp.Key,
Count = grp.Count()
};
return Json(qry.ToList() , JsonRequestBehavior.AllowGet);
}
Sounds like you could use LINQKit and its PredicateBuilder. You use it to build dynamic conditional WHERE clauses. It's also used in LinqPad, and it's free.
Try this:
public JsonResult GetChartData_IncidentsBySiteStatus(string SiteTypeId, string searchTextSite, string StartDate, string EndDate)
{
if (searchTextSite == null)
searchTextSite = "";
DateTime startDate = DateTime.Parse(StartDate);
DateTime endDate = DateTime.Parse(EndDate);
var incidentsQry = _db.Incidents;
if(SiteTypeId > -1)
{
incidentsQry = incidentsQry.Where(a=>a.SiteTypeId == SiteTypeId);
}
var qry = from s in _db.Sites
join i in incidentsQry on s.SiteId equals i.SiteId
where s.SiteDescription.Contains(searchTextSite)
&& (i.Entered >= startDate && i.Entered <= endDate)
group s by s.SiteStatus.SiteStatusDescription + "[" + s.SiteTypeId.ToString() + "]"
into grp
select new
{
Site = grp.Key,
Count = grp.Count()
};
return Json(qry.ToList() , JsonRequestBehavior.AllowGet);
}
Simply add the following to your where clause
(SiteTypeId == -1 || i.SiteTypeId == SiteTypeId)
I'm trying to get my linq statement to get me all records between two dates, and I'm not quite sure what I need to change to get it to work: (a.Start >= startDate && endDate)
var appointmentNoShow =
from a in appointments
from p in properties
from c in clients
where a.Id == p.OID && (a.Start.Date >= startDate.Date && endDate)
Just change it to
var appointmentNoShow = from a in appointments
from p in properties
from c in clients
where a.Id == p.OID &&
(a.Start.Date >= startDate.Date && a.Start.Date <= endDate)
var appointmentNoShow = from a in appointments
from p in properties
from c in clients
where a.Id == p.OID
where a.Start.Date >= startDate.Date
where a.Start.Date <= endDate.Date
var QueryNew = _context.Appointments.Include(x => x.Employee).Include(x => x.city).Where(x => x.CreatedOn >= FromDate).Where(x => x.CreatedOn <= ToDate).Where(x => x.IsActive == true).ToList();
So you are scrolling down because the Answers do not work:
This works like magic (but they say it has efficiency issues for big data, And you do not care just like me)
1- Data Type in Database is "datetime" and "nullable" in my case.
Example data format in DB is like:
2018-11-06 15:33:43.640
An in C# when converted to string is like:
2019-01-03 4:45:16 PM
So the format is :
yyyy/MM/dd hh:mm:ss tt
2- So you need to prepare your datetime variables in the proper format first:
Example 1
yourDate.ToString("yyyy/MM/dd hh:mm:ss tt")
Example 2 - Datetime range for the last 30 days
DateTime dateStart = DateTime.Now.AddDays(-30);
DateTime dateEnd = DateTime.Now.AddDays(1).AddTicks(-1);
3- Finally the linq query you lost your day trying to find (Requires EF 6)
using System.Data.Entity;
_dbContext.Shipments.Where(s => (DbFunctions.TruncateTime(s.Created_at.Value) >= dateStart && DbFunctions.TruncateTime(s.Created_at.Value) <= dateEnd)).Count();
To take time comparison into account as well :
(DbFunctions.CreateDateTime(s.Created_at.Value.Year, s.Created_at.Value.Month, s.Created_at.Value.Day, s.Created_at.Value.Hour, s.Created_at.Value.Minute, s.Created_at.Value.Second) >= dateStart && DbFunctions.CreateDateTime(s.Created_at.Value.Year, s.Created_at.Value.Month, s.Created_at.Value.Day, s.Created_at.Value.Hour, s.Created_at.Value.Minute, s.Created_at.Value.Second) <= dateEnd)
Note the following method mentioned on other stackoverflow questions and answers will not work correctly:
....
&&
(
s.Created_at.Value.Day >= dateStart.Day && s.Created_at.Value.Day <= dateEnd.Day &&
s.Created_at.Value.Month >= dateStart.Month && s.Created_at.Value.Month <= dateEnd.Month &&
s.Created_at.Value.Year >= dateStart.Year && s.Created_at.Value.Year <= dateEnd.Year
)).count();
if the start day was in this month for example and the end day is on the next month, the query will return false and no results, for example:
DatabaseCreatedAtItemThatWeWant = 2018/12/05
startDate = 2018/12/01
EndDate = 2019/01/04
the query will always search for days between 01 and 04 without taking the "month" into account, so "s.Created_at.Value.Day <= dateEnd.Day" will fail
And in case you have really big data you would execute Native SQL Query rather than linq
...
... where Shipments.Created_at BETWEEN CAST(#Created_at_from as datetime) AND CAST(#Created_at_to as datetime))
....
Thanks
If someone interested to know how to work with 2 list and between dates
var newList = firstList.Where(s => secondList.Any(secL => s.Start > secL.RangeFrom && s.End < secL.RangeTo))
public List<tbltask> gettaskssdata(int? c, int? userid, string a, string StartDate, string EndDate, int? ProjectID, int? statusid)
{
List<tbltask> tbtask = new List<tbltask>();
DateTime sdate = (StartDate != "") ? Convert.ToDateTime(StartDate).Date : new DateTime();
DateTime edate = (EndDate != "") ? Convert.ToDateTime(EndDate).Date : new DateTime();
tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).
Where(x => x.tblproject.company_id == c
&& (ProjectID == 0 || ProjectID == x.tblproject.ProjectId)
&& (statusid == 0 || statusid == x.tblstatu.StatusId)
&& (a == "" || (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)))
&& ((StartDate == "" && EndDate == "") || ((x.StartDate >= sdate && x.EndDate <= edate)))).ToList();
return tbtask;
}
this my query for search records based on searchdata and between start to end date
If you have date interval filter condition and you need to select all records which falls partly into this filter range. Assumption: records has ValidFrom and ValidTo property.
DateTime intervalDateFrom = new DateTime(1990, 01, 01);
DateTime intervalDateTo = new DateTime(2000, 01, 01);
var itemsFiltered = allItems.Where(x=>
(x.ValidFrom >= intervalDateFrom && x.ValidFrom <= intervalDateTo) ||
(x.ValidTo >= intervalDateFrom && x.ValidTo <= intervalDateTo) ||
(intervalDateFrom >= x.ValidFrom && intervalDateFrom <= x.ValidTo) ||
(intervalDateTo >= x.ValidFrom && intervalDateTo <= x.ValidTo)
);
I had a problem getting this to work.
I had two dates in a db line and I need to add them to a list for yesterday, today and tomorrow.
this is my solution:
var yesterday = DateTime.Today.AddDays(-1);
var today = DateTime.Today;
var tomorrow = DateTime.Today.AddDays(1);
var vm = new Model()
{
Yesterday = _context.Table.Where(x => x.From <= yesterday && x.To >= yesterday).ToList(),
Today = _context.Table.Where(x => x.From <= today & x.To >= today).ToList(),
Tomorrow = _context.Table.Where(x => x.From <= tomorrow & x.To >= tomorrow).ToList()
};
You can use DbFunctions.TruncateTime(StartDateTime) To remove the time from datetime
var appointmentNoShow =
from a in appointments
from p in properties
from c in clients
where a.Id == p.OID && (DbFunctions.TruncateTime(a.Start) >= DbFunctions.TruncateTime(startDate) && endDate)