I'd like to query my customers for the ones, whose birthdays are yet to come.
I've tried this query, and it - of course - has failed breathtakingly:
Addresses.Where(adr => adr.DateOfBirth != null && adr.DateOfBirth.Value >
DateTime.Now).Take(15).ToList();
Of course this can't work properly (not if you're born in the future) and I'd like to know how I can query my Nullable<DateTime> without a year?
You can do it in one line like this:
context.Addresses.Where(adr => adr.DateOfBirth != null).OrderBy(adr => EntityFunctions.DiffDays(DateTime.Today, EntityFunctions.AddYears(adr.DateOfBirth, EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today) + ((adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month)) ? 1 : 0)))).Take(15).ToList();
Or in a more readable format:
var query = from adr in context.Addresses
where adr.DateOfBirth != null
let diffYears = EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today)
let birthdayOccurred = adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month)
let nextBirthdate = EntityFunctions.AddYears(adr.DateOfBirth, diffYears + (birthdayOccurred ? 1 : 0))
let daysToBirthdate = EntityFunctions.DiffDays(DateTime.Today, nextBirthdate)
orderby daysToBirthdate
select adr;
var result = query.Take(15).ToList();
I'm not sure you can do this as a one-liner. Certainly not with any degree of clarity.
The needed steps are:
Create an ordered list containing only the birthdates where the
month/day comes after today.
Create an ordered list containing only the birthdates where the month/day is before today.
Append the second list to the first one, you now have a single list, sorted in
birthday order.
Take the first 15.
I think the C# code would look something like this (You might need to add a List or two.)
var list1 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month > DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day >= DateTime.Today.Day))).ToList();
var list2 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month < DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day < DateTime.Today.Day))).ToList();
var fullList = list1.Add(list2);
Im not familiar with Linq, I'll try to help with some pseudocode.
Most important condition should look like this:
Date(CurrentDate.Year, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate
|| ' OR
Date(CurrentDate.Year + 1, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate
This will work 31 December too.
Alternative:
// consider this as pseudocode, I didnt tested that in C#
function GetNextBirthday(DateTime DateOfBirth)
{
int yearOfNextBirthday;
int birthdayMMDD = DateOfBirth.Month*100 + DateOfBirth.Day;
int todayMMDD = CurrentDate.Month*100 + CurrentDate.Day;
if (birthdayMMDD >= todayMMDD)
{
yearOfNextBirthday = CurrentDate.Year; // this year
}
else
{
yearOfNextBirthday = CurrentDate.Year + 1; // next year
}
DateTime nextBirthday;
// you have to write this line yourself, i dont remember how to make date from Y, M, D
nextBirthday = DateFromYMD(yearOfNextBirthday, DateOfBirth.Month, DateOfBirth.Day);
return nextBirthday;
}
Here is my entry for "one liner":
DateTime now = DateTime.Now;
var next15 =
from a in db.Addresses
where a.DateOfBirth != null
let diff = EntityFunctions.DiffSeconds(
EntityFunctions.AddYears(now, -EntityFunctions.DiffYears(a.DateOfBirth, now)),
a.DateOfBirth)
orderby diff >= 0 ? diff : diff + 366*24*60*60
select new a;
var res = next15.Take(15).ToList();
Just tested with SQL Database - and it works like charm ;)
Try something like this; (this is working - I've tested)
//A mock up value for comparison (as DayOfYear not supported in Linq)
int doy = DateTime.Today.Month * 31 + DateTime.Today.Day;
var results = Addresses.Where(a => a.DateOfBirth != null)
.OrderBy( a =>
(a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day) +
(a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day > doy ? 0 : 400 ))
.Take(15).ToList();
Here's the same solution as #Aducci but with nullable date and the DBFunctions, as EntityFunctions became deprecated.
pacientes = from paciente in pacientes
where paciente.Nascimento != null
let diffYears = DbFunctions.DiffYears(paciente.Nascimento, DateTime.Today)
let birthdayOccurred = paciente.Nascimento.Value.Month < DateTime.Today.Month
|| (paciente.Nascimento.Value.Day <= DateTime.Today.Day && paciente.Nascimento.Value.Month == DateTime.Today.Month)
let nextBirthdate = DbFunctions.AddYears(paciente.Nascimento, diffYears + (birthdayOccurred ? 1 : 0))
let daysToBirthdate = DbFunctions.DiffDays(DateTime.Today, nextBirthdate)
orderby daysToBirthdate
select paciente;
Related
Could someone tell me why this query return a wrong value ?
First I generate 30 data at Player.estateagent. The Date must until 28/05.
System.DateTime Now = System.DateTime.Now;
System.DateTime thedate;
thedate = Now;
System.DateTime today = System.DateTime.Now;
for (int i = 1; i <= 30; i++) {
Player.estateagent.Add (new classBundle (thedate, false));
thedate = thedate.AddDays (1);
Debug.Log ("DATE : " + Player.estateagent [i - 1].Date);
}
int count = Player.estateagent.Where (j => {
return j.Complete == false && today.Date <= j.Date.Date;
}).Select (j=> j.Date.Date).Count ();
Debug.Log(count); // Here return 30, It must be 1
When i count i got 30 not 1. It should return 1 because i have query
where j.complete == false && today.Date <= j.Date.Date
Can someone explain what mistake that i done ?
Thanks
Yes, So far I have asked a wrong question. This is just misunderstood about the logic.
The code i am provide above is running without an error. And the logic is right too.
The result is right with 30.
But i want to have a result which Equal and Greater ( <= ) than the Player.estateagent => Date Compire to today date.
So i just need to do today.Date >= j.Date.Date.
Just like that.
I am creating application on Xamarin and on Entry I created this method:
private void expiry_TextChanged(object sender, TextChangedEventArgs e)
{
var monthCheck = new Regex(#"^(0[1-9]?|1[0-2]?)$");
var yearCheck = new Regex(#"^(1[6-9]?|2[0-9]?)$");
var dateParts = expiry.Text.Split('/');
if (!monthCheck.IsMatch(dateParts[0]) || !yearCheck.IsMatch(dateParts[1]))
{
return;
}
var year = int.Parse(dateParts[1]);
var month = int.Parse(dateParts[0]);
var lastDateOfExpiryMonth = DateTime.DaysInMonth(year, month);
var cardExpiry = new DateTime(year, month, lastDateOfExpiryMonth, 23, 59, 59);
int sizeLength = 4;
string tmpText = expiry.Text.Replace("/", "");
if (tmpText.Length > sizeLength)
{
expiry.Text = expiry.Text.Remove(expiry.Text.Length - 1);
return;
}
if (tmpText.Length > 0 && (expiry.Text.Length % 3 == 0) && expiry.Text.Substring(expiry.Text.Length - 1, 1) != "/" && expiry.Text.Substring(expiry.Text.Length - 2, 1) != "/")
{
expiry.Text = string.Concat(expiry.Text.Substring(0, expiry.Text.Length - 1), "/", expiry.Text.Substring(expiry.Text.Length - 1, 1));
}
}
On if (!monthCheck.IsMatch(dateParts[0]) || !yearCheck.IsMatch(dateParts[1])) I am getting error that Index was outside the bounds, but how it is possible if I added only symbol to my expiry Entry field?
The method ExpDate_TextChanged is getting called as soon someone enters the first character into the TextField and it's getting called for each following character. I guess it's empty by default, so the first call of this method happens while there is not yet a "/" in the TextField.
Move the code which is currently in ExpDate_TextChanged to a Button for example, so it's executed when the input is complete. And add a sanity check before accessing any of the elements in dateParts:
if (dateParts.Length < 2)
return;
}
Please note there are better methods for parsing dates like DateTime.TryParse() which I highly recommend.
Me:
You still haven't added a sample date. What can expiry.Text be?
You:
well, it could be 01/17 for example
If that is January 2017 and the expiry time should be: new DateTime(2017,1,31,23,59,59))(so the end of that month), you can use DateTime.TryParseExact:
DateTime cardExpiry;
bool validDate = DateTime.TryParseExact(expiry.Text, "MM/yy", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out cardExpiry);
if (!validDate)
{
MessageBox.Show("Enter a valid card expiry month in the format 'MM/yy', for example 01/17");
return;
}
cardExpiry = cardExpiry.AddMonths(1).AddSeconds(-1); // last date of month, 23:59:59
// ...
Thank you every one for help and suggestions, but unfortunately I solved it in other way: first of all I check does dateParts is more than 0 , instead check (dateParts.Length < 2) . My final code looks like this:
var dateParts = expiry.Text.Split('/');
if(dateParts.Length>0)
{
if(!monthCheck.IsMatch(dateParts[0]) && dateParts[0] != "")
{
if (dateParts[0].Length > 0)
dateParts[0] = dateParts[0].Substring(0, dateParts[0].Length - 1);
}
else
{
if(dateParts[0].Length==2)
dateParts[0] = dateParts[0]+ "/";
}
if(dateParts.Length > 1)
{
if (!yearCheck.IsMatch(dateParts[1]) && dateParts[1] != "")
{
if (dateParts[1].Length > 0)
dateParts[1] = dateParts[1].Substring(0, dateParts[1].Length - 1);
}
}
}
While executing the down lines of my C# controller code I was getting
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding
I use linq to sql in my c#.and result show my report form.my reporter is rdlc.
I tried like set the connect Timeout = 0; also, but I get the same error.
How can I solve it?
please help me...thanks.
private void bt10_Click(object sender, EventArgs e)
{
{
Form3 frm3 = new Form3();
DataSet ds = new DataSet();
var DB = new DataClasses3DataContext();
var c1 = (from c in DB.A
join r in DB.A1
on c.DATE equals r.DATE
where c.B.Equals(int.Parse(txtSearch.Text))
&& (string.Compare(c.DATE.ToString(), txtEdate.Text) <= 0
&& string.Compare(c.DATE.ToString(), txtFdate.Text) >= 0)
&& (c.NO == r.NO)
&& (c.K == 10)
&& (c.A == 1)
&& (r.A == 2)
&& r.K != 10
select c).ToList();
dataGridView1.DataSource = c1;
DataSet2.ADataTable dt = new DataSet2.ADataTable();
foreach (A item in c1)
{
dt.Rows.Add(item.B, item.DATE, item.NO, item.K);
}
if (c1 == null)
{
MessageBox.Show("null");
}
else
{
ds.Tables.Add(dt);
ReportDataSource rds = new ReportDataSource();
frm3.reportViewer1.LocalReport.DataSources.Clear();
rds.Name = "DataSet3";
rds.Value = dt;
frm3.reportViewer1.LocalReport.DataSources.Add(rds);
frm3.reportViewer1.LocalReport.ReportEmbeddedResource = "P10.Report5.rdlc";
frm3.ShowDialog();
}
}
}
Don't "fix" timeouts by increasing them. Fix the underlying problem!
It's very likely that convertingc.DATE to string before comparing it causes the problem. This makes the expression non-sargable, i.e. any index on DATE is disabled. You should change this by parsing txtEdate.Text and txtFdate.Text first, and use the parsed values in the comparison (and also parse txtSearch first).
var edate = DateTime.Parse(txtEdate.Text);
var fdate = DateTime.Parse(txtFdate.Text);
var searchInt = int.Parse(txtSearch.Text);
...
where c.B == searchInt
&& c.DATE <= edate
&& c.DATE >= fdate
...
If this still doesn't help you should investigate proper indexing on the database tables. For such a relatively simple query you just shouldn't get a timeout.
Use CommandTimeout Property That adds to the default time out which is 30 seconds:
DB.CommandTimeout = 1 * 60; // Adds 1 Minute to the time out, so 1:30 minutes now
If this is a long running task, you might need to consider an async method.
For More : DataContext.CommandTimeout
I have an 'IF' statement but I want the condition to check that the date of my object is not less than todays date but I can not figure out how to do this at all.
Code
private List<Web.Services.Entities.Generic.Expenditure> getTransactions(int Id, int AccountId, string Identifier)
{
if (Details != null)
{
foreach (var ABC in Details.Info.ABC)
{
if (ABC.Type == "Test" && ABC.Value.Value > 0)
{
int j = 1;
if (ABC.Frequency == "Monthly")
{
j = 3;
}
for (var i = 0; i < j; i++)
{
List.Add(new Web.Services.Entities.Generic.Expenditure
{
Amount = ABC.RegularIncome.Value * -1,
Description = "Income (" + ABC.Frequency + ")",
DueDate = (DateTime)ABC.NextDate.Value.AddMonths(i)
});
}
}
}
}
}
I tried to declare my (DateTime)ABC.NextDate.Value as a VAR above the following IF and then add to if (ABC.Type == "ABC" && ABC.Value.Value > 0) but I got the following error:
operator '&& ' cannot be applied to operands of type 'bool' and
'system.datetime'
I need to add another condition to the above IF and not replace the '0' as this is checking another value in what is returned.
To test a nullable date you do the following:
if (dateTimeToBeTested.Value.Date >= DateTime.Now.Date)
By using the .Date property, you are forcing the DateTime to midnight of the date in question, so time differences will be ignored.
To use this in your example above, you can do the following:
if (ABC.Type == "Test" && ABC.Value.Value > 0 && dateTimeToBeTested.Value.Date >= DateTime.Now.Date)
Use DateTime.Now to compare ABC.Value.Value with current date.
if (ABC.Type == "Test" && ABC.Value.Value > DateTime.Now)
Edit after question update with more required details and updated if statement.
System.Nullable' does not contain a definition for 'Date' and no
extension method 'Date' accepting...
You need to use DateTime.Value to access the Date property of nullable DateTime. Before using Date property you must check if DateTime variable has value. You can use .HasValue to ensure you have value for nullable DateTime.
Once you are sure that your datetime variable has values using .HasValue you can safely use DateProperty so you would use ABC.NextDate.Value instead of ABC.NextDate to access Date Property.
if (ABC.Type == "Test" && ABC.Value.Value > 0 && ABC.NextDate.HasValue && ABC.NextDate.Value.Date >= DateTime.Now.Date)
I have a list of DateTime Objects, this objects have a StarteDate and a EndDate. No I want to get all items that occur within a StartHour and an EndHour.
My code so far:
var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate.Date
&& x.Start.Hour >= startHour && x.End.Hour <= endHour);
This works as long as the start hor of an item is equal or larger than the startHour provided. However if for example the startHour = 09:00 and an item has Start = 8:00 and End = 10:00 it is ignored.
How can I include items that have a start hour between start hour and end hour?
Thank you!
var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate &&
(((x.Start.Hour >= startHour && x.Start.Hour < endHour) ||
(x.End.Hour > startHour && x.End.Hour <= endHour)) ||
(x.Start.Hour < startHour && x.End.Hour > endHour)));
Check to see if either the start of the event is in the time window, or the end of the event is in the time window, or whether the event overlaps the time window. (Added a fix to prevent inclusive end and start times)
Testing some more, it can be shrunk to this:
var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate &&
(x.Start.Hour < endHour && x.End.Hour > startHour));
Check if this works :
var sameDay = allItems.Where(x => x.Start.Date == calendarItem.StartDate.Date
&& x.Start.Hour >= startHour && x.Start.Hour <= endHour);