Say I have the following:
MyDate =
(db.MyTables.FirstOrDefault(x => x.MyID == idToFind).DateValue == DateTime.MinValue)
? DateTime.Now
: db.MyTables.FirstOrDefault(x => x.MyID == idToFind).DateValue
Is there any way to do this without running that LINQ query twice?
I cannot run it first into a temp variable because this query is itself part of a bigger LINQ query.
I cannot run it first into a temp variable because this query is
itself part of a bigger LINQ query.
You can use a let assignment within your query (or alternatively a projection that includes a helper field if you are using lambda syntax - that's what it gets compiled down to anyway):
var query = from foo in db.Bar
let bar = db.MyTables.FirstOrDefault(x => x.MyID == idToFind).DateValue
select new
{
MyDate = bar == DateTime.MinValue ? DateTime.Now : bar
}
Yes.
var dateValue = db.MyTables.FirstOrDefault(x => x.MyID == idToFind).DateValue;
return dateValue == DateTime.MinValue ? DateTime.Now : dateValue;
Now, when you're saying that the value can't be stuffed into a temp value, what do you mean? The above code certainly looks to be able to converted to that pattern.
Evaluate once and assign to a variable - use the variable in your conditional:
var item = db.MyTables.FirstOrDefault(x => x.MyID == idToFind);
MyDate = (item.DateValue == DateTime.MinValue)
? DateTime.Now
: item.DateValue
Or:
var theDate = db.MyTables.FirstOrDefault(x => x.MyID == idToFind).DateValue;
MyDate = (theDate == DateTime.MinValue)
? DateTime.Now
: theDate
You can still use a temporary variable, declare it but assign it inside that expression.
Lots of code might make it hard to read in some situations, but at least reduces duplication.
MyDate =
(temp = db.MyTables.FirstOrDefault(x => x.MyID == idToFind).DateValue) == DateTime.MinValue)
? DateTime.Now
: temp
Use LINQ's let statement
from a in someSource
let d = db.MyTables.FirstOrDefault(x => x.MyID == a.idToFind).DateValue
select (d == DateTime.MinValue) ? DateTime.Now : d;
Related
DateTime newDate = DateTime.Now.AddDays(-30);
var queryResultPage = (from r in CustomPlanning
where (r.Assignment == "In Use") &&
(r.CUST_SHRT_NM != null) &&
System.Convert.ToDateTime(r.lastlogontimestamp) < newDate &&
!(from uA in SurveyActivity
where uA.CustomDemandID == r.ID
select uA.CustomDemandID).Contains(r.ID)
select r)
.OrderBy(t => t.ID);
Above is my code. lastlogontimestamp is a string field in my table. i need to do this check to show the query result in a grid. Can someone please help?
ok i tried this and it worked
DateTime newDate = DateTime.Now.AddDays(-30);
var queryResultPage = (from r in CustomPlanning
where (r.Assignment == "In Use") && (r.lastlogontimestamp != null && r.lastlogontimestamp != string.Empty)
&& (r.CUST_SHRT_NM != null)
&& !(from uA in SurveyActivity where uA.CustomDemandID == r.ID select uA.CustomDemandID).Contains(r.ID)
select r).OrderBy(t => t.ID).ToList();
queryResultPage = queryResultPage.Where(r => System.Convert.ToDateTime(r.lastlogontimestamp) < newDate).ToList();
You cannot in this query directly. You need to materialize the results from the query in a list, and run another query to filter the returned CustomPlanning with Linq-To-Objects (it supports conversion).
You can convert newDate to string
string newDate = DateTime.Now.AddDays(-30).ToString();
and try to compare strings instead, but you need to cover lots and lots of cases, so it is not recommended. You can consider changing the type of lastlogontimestamp to DateTime, when you have dates, it is natural to store them as dates.
var MyCours = Db.COURS.Where(C => C.CLASSE_ID == ClassID
&& DateTime.Now>= C.START_DATE
&& DateTime.Now <= C.END_DATE)
.ToList();
Some change still dont work !
A likely problem is that the provider can't project DateTime.Compare into a SQL statement. There is potentially also a logical error in the direction of comparison (unless you really want enddate < now < startdate), and I would also suggest using .ToList() to materialize into a list:
var theTimeNow = DateTime.Now;
var MyCours = Db.COURS.Where(C => C.CLASSE_ID == ClassID
&& theTimeNow >= C.START_DATE
&& theTimeNow <= C.END_DATE)
.ToList();
Projecting DateTime.Now into a variable isolates the non-determinism of it, i.e. to ensure that both comparisons are against the same time.
I have a query like this :
result =
firstIdeaRepository.FindBy(
i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end)
.AsEnumerable()
.Select(j => new RptListOfCompanyBasedOnFirstIdeaState()
{
Name =
companyRepository.FindBy(i => i.UserId == j.UserId)
.FirstOrDefault()
DateOfMeeting =
calenderRepository.ConvertToPersianToShow(
meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id)
.FirstOrDefault()
.Date),
DateOfExit =
calenderRepository.ConvertToPersianToShow(j.DateOfExit.Value),
ReasonOfExit = j.ReasonOfExit,
}).ToList();
return result;
As you can see i use FirstOrDefault() and j.DateOfExit.Value and sometimes my Date doesn't have any values or sometime my other variables are null too because i use firstordefaut() like
companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault().
So my query throws a null exception and the result can't be created ,how can i handle this exception and for example if the .NET detects the null value ignores it by default or uses a default values for that ?
Best regards.
I would make the following changes:
result =
firstIdeaRepository.FindBy(
i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end)
.AsEnumerable()
.Select(j => new RptListOfCompanyBasedOnFirstIdeaState()
{
Name =
companyRepository.FindBy(i => i.UserId == j.UserId)
.FirstOrDefault()
DateOfMeeting =
callenderRepository.ConvertToPersianToShow(
meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id)
// project a new sequence first, before calling `FirstOrDefault`:
.Select(s => s.Date)
.FirstOrDefault(),
DateOfExit =
j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value) :
null,
ReasonOfExit = j.ReasonOfExit,
}).ToList();
When you use FirstOrDefault, there's a possibility that you'll get null back (in the case of reference types), and so you need to plan for that in your code.
For example, when assigning DateOfMeeting, you could project the results (using .Select) before using .FirstOrDefault, so that you're not ever accessing the Date property on what could be a null value.
As for DateOfExit, I've used the conditional operator to determine whether to call the calendarRepository's method at all. This assumes that DateOfExit is nullable.
Unrelated: "Calendar" is spelled with one "l" and not two.
Since you're using a nullable date, you can try filtering by values that have date, something like:
.FindBy(s => s.FirstIdeaId == j.Id && s.Date.HasValue)
This will ensure that you don't get any records with null date.
As I mentioned in comments, other cases need to be handled on case-by-case basis. Judging by the code you've shown, maybe you can handle Name as:
Name = companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault() ?? "anonymous";
and so on.
Another example:
If you do want to get the record even if DateOfMeeting is null, then add a check for HasValue in subsequent part or default it to some date:
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: (DateTime)null, // you need to make `DateOfExit` nullable and then handle that downstream
// or (default with current date)
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: callenderRepository.ConvertToPersianToShow(DateTime.Now),
// or (default with empty date)
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: callenderRepository.ConvertToPersianToShow(new DateTime()),
Moral of the story: figure out what the default value should be in case of null and then substitute that accordingly in the query when calling FirstOrDefault().
The broadest solution would be to use the idea of an null object with the DefaultIfEmpty<T>(T DefaultValue) method in your query. An example would be:
var defaultMeeting = new Meeting() { Date = new DateTime() };
var dateOfMeeting = meetingRepository.FindBy(s => s.FirstIdeaId == j.Id)
.DefaultIfEmpty(defaultMeeting)
.FirstOrDefault()
.Date;
i have linq to entities query below but i want the where clause to use the logic in sample T-SQL code after it.
var myList = from p in ctx.myTable
where !ctx.Report.Any(m => m.ReportDate == DateTime.Today && m.ReportDate == DateTime.Today)
select p;
How can i compare to month and year in my where clause like in the T-SQL below?
WHERE month(R.ReportDate) = month(GETDATE()) AND YEAR(R.ReportDate) = YEAR(GETDATE()))
Dealing with dates in LINQ to Entities is a little tricky. I'm not sure you can generate MONTH() or YEAR() within your SQL. But you can definitely generate DATEPART call with proper m or y as datepart.
Use SqlFunctions.DatePart Method (String, String) to do that:
var todayMonth = DateTime.Today.Month;
var todayYear = DateTime.Today.Year;
var myList = from p in ctx.myTable
where !ctx.Report.Any(m => SqlFunctions.DatePart("m", m.ReportDate) == todayMonth && SqlFunctions.DatePart("y", m.ReportDate) == todayYear)
select p;
Should generate
WHERE DATEPART(m, R.ReportDate) = 2 AND DATEPART(y, R.ReportDate) = 2014)
If you really want the GETDATE() part, you can use following:
var myList = from p in ctx.myTable
where !ctx.Report.Any(m => SqlFunctions.DatePart("m", m.ReportDate) == SqlFunctions.DatePart("m", SqlFunctions.GetDate()) && SqlFunctions.DatePart("y", m.ReportDate) == SqlFunctions.DatePart("y", SqlFunctions.GetDate()))
select p;
Update
I just found that page: CLR Method to Canonical Function Mapping which states, that DateTime.Month and DateTime.Year properties are translated into MONTH and YEAR methods, so following should work just fine:
var myList = from p in ctx.myTable
where !ctx.Report.Any(m => m.ReportDate.Month == SqlFunctions.GetDate().Month && m.ReportDate.Year == SqlFunctions.GetDate().Year)
select p;
A DateTime object has Month and Year property. You can make use of that.
DateTime dateTime = new DateTime();
if (dateTime.Month > DateTime.Today.Month) {
// Do something
}
if (dateTime.Year> DateTime.Today.Year)
{
// Do something
}
Try the Following Since DateTime Contains Year and Month.
where !ctx.Report.Any(m => m.ReportDate.Month == DateTime.Today.Month && m.ReportDate.Year == DateTime.Today.Year)
This is my code:
return Newsletterctx.Subscribers.Count(o =>
o.Validated == false &&
o.ValidationEmailSent == true &&
o.SubscriptionDateTime.AddMonths(1) < DateTime.Now);
I get this error:
LINQ to Entities does not recognize
the method 'System.DateTime
AddMonths(Int32)' method, and this
method cannot be translated into a
store expression.
You can use SqlFunctions classvar;
today = DateTime.Now; return Newsletterctx.Subscribers.Count(o =>
o.Validated == false &&
o.ValidationEmailSent == true &&
SqlFunctions.DateAdd("month",1,o.SubscriptionDateTime) <today);
Perhaps you can shift the date to test against instead:
DateTime testDate = DateTime.Now.AddMonths(-1);
return Newsletterctx.Subscribers.Count
(o => o.Validated == false
&& o.ValidationEmailSent == true
&& o.SubscriptionDateTime < testDate);
You have to use the Datetime outside the request because you are in the LINQ TO ENTITIES that don't use System.Datetime Library.
If you wish to use a fix date the you can define it outside the request as
DateTime compareDate = DateTime.Now.AddMonths(x);
Now, EntityFramework, Version=6 above, you can jus use System.Data.Entity.DbFunctions
return Newsletterctx.Subscribers.Count(o =>
o.Validated == false &&
o.ValidationEmailSent == true &&
DbFunctions.AddMonths(o.SubscriptionDateTime,1) < DateTime.Now);
However, in this case, use the temp variable testDate that answered by Fredrik Mörk uses less resources.