How to group linq expression only by date in datetime field - c#

Hello I need to run the following
query and group datetime field only by the date value.
var startDateTime = regDate.Date;
var endDateTime = regDate.AddSeconds(fullDayinSeconds);
var res = from u in ObjectContext.Member.Where(o => o.RegisterTime >= startDateTime && o.RegisterTime <= endDateTime)
group u by new { u.PartnerId, u.RegisterTime.Date, u.partners.Name } into pgroup
let count = pgroup.Count()
select new PartnersUsersInfo
{
PartnerId = pgroup.Key.PartnerId.GetValueOrDefault(0),
PartnerName = pgroup.Key.Name, PartnerUsersAmount = count
};
u.RegisterTime.Date - returns the exception The specified type member 'Date' is not supported in LINQ to Entities.
I have tried to use EntityFunctions.TruncateTime but it is not accepteble for group operations.
how to solve it ?

you can try add temp col with date and group by it

use
db.CallLogs.Where(r => DbFunctions.TruncateTime(r.DateTime) == callDateTime.Date).ToList();

Related

How to translate SQL to C#

I have a SQL query that looks like this:
SELECT
a.Date,
CASE
WHEN a.Type = 'String 1' OR a.Type = 'String 2'
THEN 'foo'
ELSE 'bar'
END AS VisitType,
DATEDIFF (d, (SELECT TOP 1 Date FROM dim.Date WHERE DateKey = a.StartDate),
(SELECT TOP 1 Date FROM dim.Date WHERE DateKey = a.EndDate)) AS Duration
I am trying to convert it to a C# expression and so far I have something like this:
var allowedTypes = new[]{"String 1","String 2", "String 3", "String 4"}
var Data = from a in dbContext.Claim
where a.MemberId = memberId
&& a.StartDate > startDate
&& a.EndDate <= endDate
&& a.Type.Where(???t => allowedTypes.Contains(allowedTypes)) // This line I have issues with
select new
{
Date = a.EndDate,
VisitType = ???,
VisitDuration = ???
}
I am having difficulty with the DateDiff concepts and doing a Contains like method with a string array.
ALSO I have realized that the type of the dates are contained in a nullable int.
Thanks for all your advice so far~!
Try moving the conditional into the result:
select new
{
Date = a.EndDate,
VisitType = allowedTypes.Contains(a.Type) ? "foo" : "bar",
VisitDuration = ???
}
var result = dbContext.Claims
.Where (claim => claim.MemberId = memberId
&& claim.StartDate > startDate
&& claim.EndDate <= endDate
.Select(claim => new
{
Date = claim.EndDate,
VisitType = allowedTypes.Contains(claim.Type) ? "foo" : "bar",
VisitDuration = claim.EndDate - claim.StartDate,
});
In words: given values for memberId, startDate, endDate. From the table of Claims, keep only those Claims that have a value for property MemberId that equals memberId, a value for Property startDate that is higher than startDate, and a value for endDate that is smaller than endDate.
From every Claim in the sequence of remaining Claims, make one new object with three properties.
Date is the EndDate of the Claim,
Duration is the EndDate - StartDate of the claim
If the VisityType of the Claim is in allowedTypes, then the value for property VisitType is "foo", else VisitType has a value of "bar"

LINQ left outer join on date not working

I have this collection of GroupedResult
IQueryable<GroupedResult> groupedResult = from p in db.Departure
group p by new { p.Terminal, p.DepartureDate, p.DepartureDate.Month } into g
select new GroupedResult
{
terminal = g.Key.Terminal.Code,
date = g.Key.DepartureDate,
distance = g.Count(),
month = g.Key.Month
};
The problem is that the collection I get has some dates missing. For example db.Departure contains Feb. 1, 2, 4, and 6. I also wanted to show GroupedResult for Feb. 3 and 5 so I use the following code to create a collection of dates starting from a particular start date:
var dates = new List<DateTime>();
for (var dt = date; dt <= DateTime.Now; dt = dt.AddDays(1))
{
dates.Add(dt);
}
And then join dates with groupedResult
var result = from p in groupedResult.ToList()
from q in dates.Where(r => r == p.date).DefaultIfEmpty()
select p;
The result I get is same as the one with groupedResult. How can I also show the entries with no date data?
This is because you are selecting P at the very end.....you have to create new anonymous class
var result = from q in dates
join p in groupedResult.ToList() on q equals p.date into joinedResult
from r in joinedResult.DefaultIfEmpty()
select new
{
terminal = r==null?null:r.terminal,
date = q,
distance = r==null?null:r.distance,
month = r==null?null:r.month
};
var result = from p in groupedResult.ToList()
from q in dates.Where(r => r == p.date).DefaultIfEmpty()
select p;
You've got the left join the wrong way around. You're selecting all items from your groupedResult and then ask LINQ to get all dates - or none if there is none - that match a date that already exists in the groupedResult.
var result = from q in dates
from p in groupedResult.Where(r => r.date == q).DefaultIfEmpty()
select new { Date = q, Items = p };
This works, because you select all dates and search for matching grouped items instead.

Linq comparing 2 dates

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;

How to write LINQ to SQL query for getting today date records?

I want to get the today entered records using LINQ to SQL. I wrote the below code but it is returning previous date records also.
DateTime todaysDate = DateTime.Now;
DateTime yesterdaysDate = DateTime.Now.AddDays(-1);
var result = (from a in cxt.visitor.OrderByDescending(n => n.singin)
where (a.singin > yesterdaysDate && a.singin <= todaysDate)
select new {a.visitorid, a.visitorname, a.visitingperson, a.phonenumber, a.reasonforvisit, a.signature, a.singin });
Can you please tell me how to get the today entered records only using LINQ to SQL?
Insetad of DateTime.Now use DateTime.Today like:
DateTime startDateTime = DateTime.Today; //Today at 00:00:00
DateTime endDateTime = DateTime.Today.AddDays(1).AddTicks(-1); //Today at 23:59:59
var result = (from a in cxt.visitor.OrderByDescending(n => n.singin)
where (a.singin >= startDateTime && a.singin <= endDateTime)
select new {a.visitorid, a.visitorname, a.visitingperson, a.phonenumber, a.reasonforvisit, a.signature, a.singin });
or You can try the following simpler version, (I am not sure if that would translate into SQL)
var result = (from a in cxt.visitor.OrderByDescending(n => n.singin)
where (a.singin.Date == DateTime.Today)
select new {a.visitorid, a.visitorname, a.visitingperson, a.phonenumber, a.reasonforvisit, a.signature, a.singin });

LINQ to SQL Conditional where clause

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)

Categories

Resources