查询即将到来的生日

我想询问我的客户,他们的生日还未到来。

我已经尝试过这个查询,当然 – 它已经失败了:

Addresses.Where(adr => adr.DateOfBirth != null && adr.DateOfBirth.Value > DateTime.Now).Take(15).ToList(); 

当然这不能正常工作(如果你将来出生的话),我想知道如何在没有一年的情况下查询我的Nullable

你可以在一行中这样做:

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

或者以更易读的格式:

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

我不确定你能否做到这一点。 当然没有任何清晰度。

所需的步骤是:

  1. 创建一个有序列表,其中仅包含今天之后月/日的生日。
  2. 创建一个有序列表,其中仅包含月/日所在的出生日期。
  3. 将第二个列表附加到第一个列表,您现在有一个列表,按生日顺序排序。
  4. 拿第15个。

我认为C#代码看起来像这样(你可能需要添加一个或两个List。)

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

尝试这样的事情; (这是有效的 – 我已经测试过了)

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

我不熟悉Linq,我会尝试帮助一些伪代码。

最重要的条件应如下所示:

 Date(CurrentDate.Year, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate || ' OR Date(CurrentDate.Year + 1, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate 

这将在12月31日也有效。

替代方案:

 // 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; } 

这是我的“一个class轮”的条目:

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

刚刚使用SQL数据库进行测试 – 它就像魅力一样;)

这是与@Aducci相同的解决方案,但具有可空日期和DBFunctions,因为EntityFunctions已被弃用。

  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;