我的应用程序使用付款处理供应商自动为订阅的客户开帐单。我只保留有关卡有效期的信息以及自动计费的供应商参考号。我每天都想检查会员卡在30天内到期的情况。我正在运行一个后台进程来发送电子邮件提醒。我正在努力让Linq接受我的查询。到期日期以字符串形式存储在数据库中,例如,2019年3月为0319。我想知道是否有任何机会使它生效。如果可以的话,请协助。我的最后一招可能是将当前存储为字符串mmyy的到期日期格式化为正确的日期。
int mon = DateTime.Now.Month;
int yr = DateTime.Now.Year;
int days = DateTime.DaysInMonth(yr, mon);
int dy = DateTime.Now.Day;
var allCardExpiring = db.DirectDebits.Include(i => i.Customer).Where(a =>a.DdOk && a.Customer.PassOk && DateTime.DaysInMonth(Convert.ToInt32(a.DateExpiry.Substring(2, 4)), Convert.ToInt32(a.DateExpiry.Substring(0, 2)))+days-dy < 30).Select(a => a.DirectDebitId).Distinct().ToList();
答案 0 :(得分:2)
这是一个很好的示例,表明您不应将数据库形成为操作员用来输入其输入的格式。如果您的数据库将ExpiryDate
作为DateTime,则不会遇到此问题。当然,在操作员输入其到期日期时,您必须将其转换为DateTime,但是(1)比转换回日期更容易,并且(2)您更经常使用什么:查询ExpiryDate或更新它? / p>
如果您对此数据库感到困惑,那么我的建议是创建一个查询,在其中使用{{3}将MonthYear
属性分为Month
和Year
}和DbFunctions.Left,然后使用DbFunctions.Right
如果您需要其他函数的此转换,请考虑为此创建单独的IQueryable函数,以便重新使用它。
作为DirectDebit的扩展函数,它采用DirectDebits的输入序列并返回DateTimeDirectDebit序列:
public static IQueryable<DateTimeDirectDebit> ToDateTimeDirectDebits(
this IQueryable<DirectDebit> directDebits)
{
return directDebits.Select(directDebit => new
{
// split ExpiryDate into a Month and a Year
ExpiryDate = new
{
Month = DbFunctions.Left(directDebit.DateExpire, 2),
Year = DbFunctions.Right(directDebit.DateExpire, 2),
}
DirectDebit = directDebit,
})
.Select(directDebit => new DateTimeDirectDebit
{
// create the ExpiryDate as DateTime
ExpiryDate = DbFunctions.CreateDateTime(
directDebit.ExpiryDate.Year,
directDebit.ExpiryDate.Mnth,
1, // first day of the month
...),
DirectDebit = directDebit.DirectDebit,
});
}
您还需要一个函数,该函数返回在特定天数内到期的DateTimeDirectDebits。再次作为扩展方法:
public static IQueryable<DateTimeDirectDebit> WhereExpiresWithinDays(
this IQueryable<DateTimeDirectDebit> source,
int nrOfDays)
{
DateTime now = DateTime.now;
DateTime limitDate = now.AddDays(nrOfDays);
return source.Where(directDebit => directDebit.ExpiryDate < limitDate);
}
类似地,您可能希望使用一个返回下个月到期的所有directDebits的函数,为此使用DbFunctions.DiffMonths。
用法:
using (var dbContext = new ...)
{
var directDebitsThatExpireNextMonth = dbContext.DirectDebits
.ToDateTimeDirectDebits
.WhereExpiresWithinDays(30)
.Select(...);
}
令人高兴的是,通过使用这些类似LINQ的扩展方法,您可以隐藏数据库的结构,尤其是您不满意的部分。这样,如果数据库在内部进行更改,尤其是那些不使用这些更改的函数,则不必对代码进行太多的重组。
当然,为了正确隐藏数据库结构,类DateTimeDirectDebits不应公开DirectDebits属性,而应公开要显示给外界的属性。