Return String instead of DateTime if LINQ Query NULL - linq

I am using JQuery Datatables with my MVC 5 application. I am implementing sorting on one of my datatables within my MVC Controller. One of the columns displays dates to the user, and I want them to be able to sort this column, which works fine.
//Get index of column to be sorted
var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
Func<survey_status, DateTime> orderingFunctionDate;
orderingFunctionDate = (c => c.InitiatedDate == null ? default(DateTime) : c.InitiatedDate.Value);
The problem is, at the moment, if c.InitiatedDate is NULL, then I return the default date 01/01/0001, otherwise I return the actual date recorded in the Database.
I don't like that I am returning 01/01/0001 to the user, it isn't great usability and could confuse them. Instead, I'd like to return something like "No date available" if c.InitiatedDate is NULL.
The problem is I can't replace
orderingFunctionDate = (c => c.InitiatedDate == null ? default(DateTime) : c.InitiatedDate.Value);
with
orderingFunctionDate = (c => c.InitiatedDate == null ? "No date available" : c.InitiatedDate.Value);
because the Function Func<survey_status, DateTime> orderingFunctionDate is returning a DateTime, not string and in making this change I get an error no implicit conversion between string and DateTime.
Can anyone help me out with this?
Any help would be greatly appreciated.
Thanks.

You should use a nullabel DateTime and return null instead of a default date. Change your function prototype to:
Func<survey_status, DateTime?> orderingFunctionDate;
And the content to:
orderingFunctionDate = (c => c.InitiatedDate);
Then I believe in jQuery DataTables you can specify a value to use when data is null.

Related

Entity Framework Pagination (Select records using string datetime column)

I have a table which has startdate (in format "yyyymmddhhss")and the corresponding entity attribute is string type. I would like to use LINQ To SQL get all the records with StartDate >= SelectedStartDate. Since this table has more than 10 million records, I need to use pagination as well.
Could anyone please suggest on how to implement this/
Regards,
Raaj
The best solution would be of course to migrate the string values to a DATETIME column and query the data from that column.
But if you don't have enough privileges to do that, you're lucky you have the format yyyymmddhhss in your table because that preserves the natural order of dates; all you have to do is to convert the parameter to a string in the required format:
public IEnumerable<YourDataObject> GetData(DateTime date, PageInfo pageInfo)
{
var startDate = date.ToString("yyyyMMddHHss");
return _dbContext.Table
.OrderBy(x => x.StartDate)
.Where(x => String.Compare(x.StartDate, startDate) >= 1)
.Skip(pageInfo.PageSize * pageInfo.PageIndex)
.Take(pageInfo.PageSize)
.Select(x => new YourDataObject
{
//
});
}
Here is a sample output in LINQPad:

How to convert a string into a datetime in Linq to Entities query?

My Linq to entities query is written as below.
The datatype of DATECOLUMN1 in my ORACLE database is of string.
Datetime FilterStartDate = DateTime.Now;
var query = from c in db.TABLE1
join l in db.TABLE2 on c.FK equals l.PK
where (FilterStartDate >= DateTime.ParseExact(l.DATECOLUMN1, "dd/MM/yyyy", CultureInfo.InvariantCulture) : false) == true
select c;
Writing above query gives me an error of not supported. How can I convert DATECOLUMN1 into a datetime to compare it.
P.S. I do not have control over database schema, so changing datatype of column in Oracle database is not a feasible solution for me.
In you Model, add the following property to your partial class TABLE2:
public DateTime DATECOLUMN1_NEW
{
get
{
return DateTime.ParseExact(DATECOLUMN1, "dd/MM/yyyy", CultureInfo.InvariantCulture);
}
set { }
}
Then, in you LINQ query, use DATECOLUMN1_NEW (it's already in DateTime format) in place of DATECOLUMN1.
Erm.. I think the problem you are having is that you are putting ": false" in there.
It looks like you are trying to use a condtional operator (?:) but you forgot the "?".
I don't think you actually need this as you are just trying to determine if the date is greater or not. Also if ParseExact fails it will throw an exception (not what you want) so you should use TryParse instead and handle the true/false returned and the out value to determine whether or not the date is (a) Actually a date (b) less then FilterStartDate.
You can use two alternatives:
Use the function described in the answer here: How to I use TryParse in a linq query of xml data?
Use the following fluent syntax version which I think is more readable.
var query = db.Table1.Join(db.Table2, x => x.FK, y => y.PK, (x, y) => x).Where(x =>
{
DateTime Result;
DateTime.TryParse(x.Date, out Result);
return DateTime.TryParse(x.Date, out Result) && FilterStartDate >= Result;
});

The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties

Using this code in Entity Framework I receive the following error. I need to get all the rows for a specific date, DateTimeStart is of type DataType in this format 2013-01-30 12:00:00.000
Code:
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => x.DateTimeStart.Date == currentDateTime.Date);
Error:
base {System.SystemException} = {"The specified type member 'Date' is
not supported in LINQ to Entities. Only initializers, entity members,
and entity navigation properties are supported."}
Any ideas how to fix it?
DateTime.Date cannot be converted to SQL. Use EntityFunctions.TruncateTime method to get date part.
var eventsCustom = eventCustomRepository
.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => EntityFunctions.TruncateTime(x.DateTimeStart) == currentDate.Date);
UPDATE: As #shankbond mentioned in comments, in Entity Framework 6 EntityFunctions is obsolete, and you should use DbFunctions class, which is shipped with Entity Framework.
You should now use DbFunctions.TruncateTime
var anyCalls = _db.CallLogs.Where(r => DbFunctions.TruncateTime(r.DateTime) == callDateTime.Date).ToList();
EntityFunctions is obsolete. Consider using DbFunctions instead.
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => DbFunctions.TruncateTime(x.DateTimeStart) == currentDate.Date);
I would like to add a solution, that have helpt me to solve this problem in entity framework:
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => x.DateTimeStart.Year == currentDateTime.Year &&
x.DateTimeStart.Month== currentDateTime.Month &&
x.DateTimeStart.Day == currentDateTime.Day
);
I hope that it helps.
Always use EntityFunctions.TruncateTime() for both x.DateTimeStart and currentDate.
such as :
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference).Where(x => EntityFunctions.TruncateTime(x.DateTimeStart) == EntityFunctions.TruncateTime(currentDate));
Just use simple properties.
var tomorrow = currentDateTime.Date + 1;
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => x.DateTimeStart >= currentDateTime.Date
and x.DateTimeStart < tomorrow);
If future dates are not possible in your app, then >= x.DateTimeStart >= currentDateTime.Date is sufficient.
if you have more complex date comparisons, then check Canonical functions
and if you have EF6+ DB functions
More Generally - For people searching for issues Supported Linq methods in EF
can explain similar issues with linq statements that work on Memory base Lists but not in EF.
Simplified:
DateTime time = System.DateTime.Now;
ModelName m = context.TableName.Where(x=> DbFunctions.TruncateTime(x.Date) == time.Date)).FirstOrDefault();
Use the bellow code for using EF6:
(DbFunctions.TruncateTime(x.User.LeaveDate.Value)
I have the same issue with Entity Framework 6.1.3
But with different scenario. My model property is of type nullable DateTime
DateTime? CreatedDate { get; set; }
So I need to query on today's date to check all the record, so this what works for me. Which means I need to truncate both records to get the proper query on DbContext:
Where(w => DbFunctions.TruncateTime(w.CreatedDate) == DbFunctions.TruncateTime(DateTime.Now);
Another solution could be:
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference).AsEnumerable()
.Where(x => x.DateTimeStart.Date == currentDate.Date).AsQueryable();
I've faced this same issue and it seems that it is really caused by the presence of a call to the .Date property within the Where method. When removed, the error disappears. Consider that calling the .Date property on any side of the comparison operator causes this error. Calling the .Date property outside and before the Where method is enough to solve this error.

LINQ to dataset: CopyToDataTable()

I want to query a datatable (dt) and load a 2nd dt with the resultant collection of datarows. Fine - we have the CopyToDataTable() extn mthd for exactly that purpose. However it is constrained to enumerate only over DataRows, which means that I cannot return anything else e.g. a collection of anonymous types. So - how can I modify the values in the datarows?
Eg I have a dt with 3 columns: MyPK, VARCHAR01, VARCHAR02.
Foreach row, if VARCHAR01 or VARCHAR02 has the value "" (i.e. String.Empty) I want to replace that with NULL (which the underlying type allows).
I would do this as follows:
var MyCleanedDatarows =
from o in ds.Tables["dt"].AsEnumerable()
select new {
MyPK = o.Field<string>("MyPK"),
VARCHAR01 = (o.Field<string?>("VARCHAR01") == "" ? NULL : o.Field<string?>("VARCHAR01") ),
VARCHAR02 = (o.Field<string?>("VARCHAR02") == "" ? NULL : o.Field<string?>("VARCHAR02") )
};
...but then I cant use CopyToDataTable() to get back to a dt. I'm thinking I need to modify the datarows before invoking select operator, but I dont know how to achieve that. Any help/thoughts would be v.greatfully recieved.
Thanks in advance,
Tamim.
Take a look at this approach, in MSDN documentation.
http://msdn.microsoft.com/en-us/library/bb669096.aspx

Null value cannot be assigned - LINQ query question

I have the following LINQ query:
DataClassesDataContext dc = new DataClassesDataContext();
var query = from contact in dc.Contacts
select new
{
ContactId = contact.ContactId,
LastName = contact.LastName,
FirstName = contact.FirstName,
Addresses = contact.Addresses,
Phones = contact.Phones,
DOB = contact.BirthDate,
LastNote = contact.Notes.Max(n => n.Created), //this line causes the error
Status = contact.ContactStatus.ContactStatusName,
EmailAddress = contact.Emails
};
The line where I get the maximum created date for the notes collection causes the following exception to be thrown:
Exception: The null value cannot be assigned to a
member with type System.DateTime which
is a non-nullable value type.
How do I write the query to allow null values into the LastNote field? The DOB field is defined as DateTime? and has not problem handling nulls.
Think I figured it out.
If I cast the maximum note value to a nullable DateTime it seems to eliminate the exception. The following change worked for me:
LastNote = (Nullable<DateTime>)contact.Notes.Max(n => n.Created)
As others have pointed out, it can also be written using the shorthand notation for a nullable DateTime as follows:
LastNote = (DateTime?) contact.Notes.Max(n => n.Created)
Rewrite that line as:
LastNote = (DateTime?) contact.Notes.Max(n => n.Created),
LastNote = contact.Notes.Max(n => (DateTime?)n.Created)
Couldn't find this on the net so i hope this helps others.
In VB is something like:
LastNote = CType(contact.Notes.Max(n => n.Created), Global.System.Nullable(Of Date))
I think...
You could do that, or you could alter your database schema so that the column 'Created' does not allow nulls.
The scenario is arising because one of the rows comes back with a null value for Created.
If the db didn't allow nulls, the scenario would never occur.

Resources