LINQ throwing exception when attempting to compare dates - c#

I have the following:
return db.Events
.Where(e =>
e.BedId == bed
&& e.Date.Year == date.Year
&& e.Date.Month == date.Month
&& e.Date.Day == date.Day)
.Select(x => new EventViewModel() {
Id = x.Id,
Date = x.Date.Date.ToString(),
StartTime = x.StartTime.ToString(),
EndTime = x.EndTime.ToString(),
Planned = x.Planned,
EngineSN = x.EngineSN,
Details = x.Details,
Bed = x.Bed.Name,
Category = x.Subcategory.Category.Name,
Subcategory = x.Subcategory.Name,
Project = x.Project.Name,
Type = x.Type.ToString()
})
.ToList();
It complains that member 'date' is not supported by LINQ
I am aware that LINQ can't work with dates as it has no concept of how to read and compare them. That is why I specifically asked it to compare the Year Month and Day properties (all are ints). What in my query is throwing this exception?
P.S. EventViewModel.Date is a String

You need to change your query so you aren't calling the Date property on DateTime and change your view model.
Define your DateTime properties that you defined as string as DateTime.
Annotate the DateTime properties like this
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime? Date{ get; set; }
or whatever date format you are using in your UI.
Change your query like this
var startDate = date.Date;
var endDate = date.Date.AddDays(1);
return db.Events
.Where(e =>
e.BedId == bed
&& e.Date >= startDate
&& e.Date < endDate)
.Select(x => new EventViewModel()
{
Id = x.Id,
Date = x.Date,
StartTime = x.StartTime,
EndTime = x.EndTime,
Planned = x.Planned,
EngineSN = x.EngineSN,
Details = x.Details,
Bed = x.Bed.Name,
Category = x.Subcategory.Category.Name,
Subcategory = x.Subcategory.Name,
Project = x.Project.Name,
Type = x.Type.ToString()
})
.ToList();

It looks like what you're trying to do is exclude the time portion of the date in your comparison and in your projection. If that's the case, use DbFunctions.
.Where(DbFunctions.TruncateTime(e.Date == date))
and then
Date = DbFunctions.TruncateTime(x.Date)

LINQ works with Dates as mentioned by others. It is your SELECT that is complaining at x.Date.Date.ToString()

Related

How to group linq expression only by date in datetime field

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();

Linq where clause compare only date value without time value

var _My_ResetSet_Array = _DB
.tbl_MyTable
.Where(x => x.Active == true
&& x.DateTimeValueColumn <= DateTime.Now)
.Select(x => x);
Upper query is working correct.
But I want to check only date value only.
But upper query check date + time value.
In traditional mssql, I could write query like below.
SELECT * FROM dbo.tbl_MyTable
WHERE
CAST(CONVERT(CHAR(10), DateTimeValueColumn, 102) AS DATE) <=
CAST(CONVERT(CHAR(10),GETDATE(),102) AS DATE)
AND
Active = 1
So could anyone give me suggestion how could I check only date value in Linq.
There is also EntityFunctions.TruncateTime or DbFunctions.TruncateTime in EF 6.0 or later
Simple workaround to this problem to compare date part only
var _My_ResetSet_Array = _DB
.tbl_MyTable
.Where(x => x.Active == true &&
x.DateTimeValueColumn.Year == DateTime.Now.Year
&& x.DateTimeValueColumn.Month == DateTime.Now.Month
&& x.DateTimeValueColumn.Day == DateTime.Now.Day);
Because 'Date' datatype is not supported by linq to entity , where as Year, Month and Day are 'int' datatypes and are supported.
EDIT
To avoid this error : The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
var _My_ResetSet_Array = _DB
.tbl_MyTable
.Where(x => x.Active == true)
.Select(x => x).ToList();
var filterdata = _My_ResetSet_Array
.Where(x=>DateTime.Compare(x.DateTimeValueColumn.Date, DateTime.Now.Date) <= 0 );
The second line is required because LINQ to Entity is not able to convert date property to sql query. So its better to first fetch the data and then apply the date filter.
EDIT
If you just want to compare the date value of the date time than make use of
DateTime.Date Property - Gets the date component of this instance.
Code for you
var _My_ResetSet_Array = _DB
.tbl_MyTable
.Where(x => x.Active == true
&& DateTime.Compare(x.DateTimeValueColumn.Date, DateTime.Now.Date) <= 0 )
.Select(x => x);
If its like that then use
DateTime.Compare Method - Compares two instances of DateTime and returns an integer that indicates whether the first instance is earlier than, the same as, or later than the second instance.
Code for you
var _My_ResetSet_Array = _DB
.tbl_MyTable
.Where(x => x.Active == true
&& DateTime.Compare(x.DateTimeValueColumn, DateTime.Now) <= 0 )
.Select(x => x);
Example
DateTime date1 = new DateTime(2009, 8, 1, 0, 0, 0);
DateTime date2 = new DateTime(2009, 8, 1, 12, 0, 0);
int result = DateTime.Compare(date1, date2);
string relationship;
if (result < 0)
relationship = "is earlier than";
else if (result == 0)
relationship = "is the same time as";
else
relationship = "is later than";
result = from r in result where (r.Reserchflag == true &&
(r.ResearchDate.Value.Date >= FromDate.Date &&
r.ResearchDate.Value.Date <= ToDate.Date)) select r;
&& x.DateTimeValueColumn <= DateTime.Now
This is supported so long as your schema is correct
&& x.DateTimeValueColumn.Value.Date <=DateTime.Now
In similar case I used the following code:
DateTime upperBound = DateTime.Today.AddDays(1); // If today is October 9, then upperBound is set to 2012-10-10 00:00:00
return var _My_ResetSet_Array = _DB
.tbl_MyTable
.Where(x => x.Active == true
&& x.DateTimeValueColumn < upperBound) // Accepts all dates earlier than October 10, time of day doesn't matter here
.Select(x => x);
Working code :
{
DataBaseEntity db = new DataBaseEntity (); //This is EF entity
string dateCheck="5/21/2018";
var list= db.tbl
.where(x=>(x.DOE.Value.Month
+"/"+x.DOE.Value.Day
+"/"+x.DOE.Value.Year)
.ToString()
.Contains(dateCheck))
}
Try this,
var _My_ResetSet_Array = _DB
.tbl_MyTable
.Where(x => x.Active == true
&& x.DateTimeValueColumn <= DateTime.Now)
.Select(x => x.DateTimeValueColumn)
.AsEnumerable()
.select(p=>p.DateTimeValueColumn.value.toString("YYYY-MMM-dd");
Do not simplify the code to avoid "linq translation error":
The test consist between a date with time at 0:0:0 and the same date with time at 23:59:59
iFilter.MyDate1 = DateTime.Today; // or DateTime.MinValue
// GET
var tempQuery = ctx.MyTable.AsQueryable();
if (iFilter.MyDate1 != DateTime.MinValue)
{
TimeSpan temp24h = new TimeSpan(23,59,59);
DateTime tempEndMyDate1 = iFilter.MyDate1.Add(temp24h);
// DO not change the code below, you need 2 date variables...
tempQuery = tempQuery.Where(w => w.MyDate2 >= iFilter.MyDate1
&& w.MyDate2 <= tempEndMyDate1);
}
List<MyTable> returnObject = tempQuery.ToList();
Use mydate.Date to work with the date part of the DateTime class only.

Linq Join tables, Group by date, Sum of values?

I have two tables (one-to-many). MeterReadings(0..1) and MeterReadingDetails(*)
I want to join these tables and group by date. Date field is in MeterReadings and Others are in MeterReadingDetails.
I used this code:
Linq
public static IEnumerable<MeterReadingsForChart> GetCustomerTotal(int CustomerId, int MeterTypeId, DateTime StartDate, DateTime EndDate, MeterReadingsTimeIntervals DateRangeType)
{
var customerReadings = from m in entity.MeterReadings
join n in entity.MeterReadingDetails on m.sno equals n.ReadingId
where m.Meters.CustomerId == CustomerId && m.ReadDate >= StartDate && m.ReadDate <= EndDate && m.Meters.TypeId == MeterTypeId
group n by new { date = new DateTime(m.ReadDate.Value.Year, m.ReadDate.Value.Month, 1) } into g
select new MeterReadingsForChart
{
ReadDate = g.Key.date,
Value = g.Sum(x => x.Value),
Name = g.FirstOrDefault().MeterReadingTypes.TypeName
};
return customerReadings;
}
MeterReadinsForChart.cs
public class MeterReadingsForChart
{
public DateTime ReadDate { get; set; }
public string Name { get; set; }
public double Value { get; set; }
}
But I got this error:
Only parameterless constructors and initializers are supported in LINQ to Entities
How can I join, group, and sum?
Try the following:
var customerReadings = (from m in entity.MeterReadings
join n in entity.MeterReadingDetails on m.sno equals n.ReadingId
where m.Meters.CustomerId == CustomerId && m.ReadDate >= StartDate && m.ReadDate <= EndDate && m.Meters.TypeId == MeterTypeId
group n by new { Year = m.ReadDate.Value.Year, Month = m.ReadDate.Value.Month} into g
select new
{
Key = g.Key,
Value = g.Sum(x => x.Value),
Name = g.FirstOrDefault().MeterReadingTypes.TypeName
}).AsEnumerable()
.Select(anon => new MeterReadingsForChart
{
ReadDate = new DateTime(anon.Key.Year, anon.Key.Month, 1),
Value = anon.Value,
Name = anon.Name
});
Unf. its ugly, but entity framework won't let you create a DateTime (being a struct it has no parameterless constructors). So in this case we want most of the result from the db and then as this streams we construct the date in memory.

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)

How to query current week & current month report by using LINQ to XML?

I am developing window phone 7 application in silverlight. I am new to the silverlight. I am also new to LINQ to XML. In my application the user select the date & submit some transaction details into the application. The details gets stored in XML File. I am using the custom date control in my application for the date selection as follows
private void DatePicker_ValueChanged(object sender, DateTimeValueChangedEventArgs e)
{
AppObj = Application.Current as App;
AppObj.date = (DateTime)EntryDate.Value;
}
Then the value of AppObj.date gets stored in the XML file. Sometimes I use the DateTime.Now to store the date in the XML File. Now I want to generate the report of submitted transaction details by querying through LINQ to XML. I want to generate the report for today's date, current week & current month. For today's date report I am using the following code
public class TransactionList : List<Transaction>
{
public void GetTransactionObjects(String strXMLFile, int Currency_ID, int TransactionType_ID)
{
XDocument doc = null;
XMLFileManager XMLDocObj = new XMLFileManager();
doc = XMLDocObj.LoadXMLFile(strXMLFile);
DateTime today = DateTime.Today;
var vTransaction = doc.Descendants("Transaction")
.Where(x => ((DateTime)x.Element("Current_Date")).Date == today)
.Where(x => x.Element("TransactionType_ID").Value == TransactionType_ID.ToString())
.Where(x => x.Element("Currency_ID").Value == Currency_ID.ToString())
.Select(x => new Transaction(x));
this.Clear();
AddRange(vTransaction);
}
}
The Transaction class contains the following constructor.
public Transaction(XElement xElement)
{
Transaction_ID = Convert.ToInt32(xElement.Element("Transaction_ID").Value.ToString());
TransactionType_ID = Convert.ToInt32(xElement.Element("TransactionType_ID").Value.ToString());
Alphabet_ID = Convert.ToInt32(xElement.Element("Alphabet_ID").Value.ToString());
ID = Convert.ToInt32(xElement.Element("ID").Value.ToString());
SubCategory_ID = Convert.ToInt32(xElement.Element("SubCategory_ID").Value.ToString());
Item_ID = Convert.ToInt32(xElement.Element("Item_ID").Value.ToString());
Currency_ID = Convert.ToInt32(xElement.Element("Currency_ID").Value.ToString());
InputTypeMethod_ID = Convert.ToInt32(xElement.Element("InputTypeMethod_ID").Value.ToString());
Principle = Convert.ToInt32(xElement.Element("InputTypeMethod_ID").Value.ToString());
Interest = Convert.ToInt32(xElement.Element("Interest").Value.ToString());
ROI = Convert.ToInt32(xElement.Element("InputTypeMethod_ID").Value.ToString());
Amount = Convert.ToInt32(xElement.Element("Amount").Value.ToString());
//Current_Date = Convert.ToDateTime(xElement.Element("Current_Date").Value.ToString());
Current_Date = ((DateTime)xElement.Element("Current_Date")).Date;
}
In the XML File the value gets stored for date & time. The value gets stored as follows
<Transactions>
<Transaction>
<Transaction_ID>0</Transaction_ID>
<TransactionType_ID>0</TransactionType_ID>
<Alphabet_ID>3</Alphabet_ID>
<ID>0</ID>
<SubCategory_ID>0</SubCategory_ID>
<Item_ID>0</Item_ID>
<Currency_ID>3</Currency_ID>
<InputTypeMethod_ID>0</InputTypeMethod_ID>
<Principle>0</Principle>
<Interest>0</Interest>
<ROI>0</ROI>
<Amount>5000</Amount>
<Current_Date>2010-12-31T18:08:23.433+05:30</Current_Date>
</Transaction>
</Transactions>
Look at the node
2010-12-31T18:08:23.433+05:30
The date format is yyyy-mm-dd.
Now how should I write the following query to get all the submitted transaction details for current week as well as current month ?
var vTransaction = doc.Descendants("Transaction")
.Where(x => ((DateTime)x.Element("Current_Date")).Date == today)
.Where(x => x.Element("TransactionType_ID").Value == TransactionType_ID.ToString())
.Where(x => x.Element("Currency_ID").Value == Currency_ID.ToString())
.Select(x => new Transaction(x));
Can you please provide me any code or link through which I can resolve the above issue ? If I am doing anything wrong then please guide me.
The DateTime object has a property Month, with that you should be able to filter on month. For week you could use the GetWeekOfYear in the Calendar class, read this link: http://msdn.microsoft.com/en-us/library/system.globalization.calendar.getweekofyear.aspx
The following code will give the current week summary :
DateTime startDate = DateTime.Today.Date.AddDays(-(int)DateTime.Today.DayOfWeek), // prev sunday 00:00
endDate = startDate.AddDays(7); // next sunday 00:00
var vTransaction = from x in doc.Descendants("Transaction")
where ((DateTime)x.Element("Current_Date")).Date >= startDate
&& ((DateTime)x.Element("Current_Date")).Date < endDate
where x.Element("TransactionType_ID").Value == TransactionType_ID.ToString()
select new Transaction(x);
The Following code will give the current month summary
int CurrentYear = DateTime.Today.Year;
int CurrentMonth = DateTime.Today.Month;
DateTime startDate = new DateTime(CurrentYear, CurrentMonth, 1);
DateTime endDate = startDate.AddMonths(1).AddMinutes(-1);
var vTransaction = from x in doc.Descendants("Transaction")
where ((DateTime)x.Element("Current_Date")).Date >= startDate
&& ((DateTime)x.Element("Current_Date")).Date < endDate
where x.Element("TransactionType_ID").Value == TransactionType_ID.ToString()
select new Transaction(x);
OR both the queries can be wriiten for the current week of selected date & current month of selected date as follows
public void GetCurrentWeekSummary(String strXMLFile, int TransactionType_ID, DateTime selectedDate)
{
XDocument doc = null;
XMLFileManager XMLDocObj = new XMLFileManager();
doc = XMLDocObj.LoadXMLFile(strXMLFile);
DateTime startDate = selectedDate.Date.AddDays(-(int)selectedDate.DayOfWeek), // prev sunday 00:00
endDate = startDate.AddDays(7); // next sunday 00:00
var vTransaction = from x in doc.Descendants("Transaction")
where ((DateTime)x.Element("Current_Date")).Date >= startDate
&& ((DateTime)x.Element("Current_Date")).Date < endDate
where x.Element("TransactionType_ID").Value == TransactionType_ID.ToString()
select new Transaction(x);
}
public void GetCurrentMonthSummary(String strXMLFile, int TransactionType_ID, DateTime selectedDate)
{
XDocument doc = null;
XMLFileManager XMLDocObj = new XMLFileManager();
doc = XMLDocObj.LoadXMLFile(strXMLFile);
int CurrentYear = selectedDate.Year;
int CurrentMonth = selectedDate.Month;
DateTime startDate = new DateTime(CurrentYear, CurrentMonth, 1);
DateTime endDate = startDate.AddMonths(1).AddMinutes(-1);
var vTransaction = from x in doc.Descendants("Transaction")
where ((DateTime)x.Element("Current_Date")).Date >= startDate
&& ((DateTime)x.Element("Current_Date")).Date < endDate
where x.Element("TransactionType_ID").Value == TransactionType_ID.ToString()
select new Transaction(x);
}

Categories

Resources