EF DateTime格式

时间:2018-08-22 15:34:01

标签: c# entity-framework linq datetime iqueryable

我首先使用EF 6代码,并且需要像dateTime上那样以特定格式(例如IE)执行sql:

我的第一次尝试是顺其自然:

var users = context.User
       .Where(x => x.BirthDate.ToString("dd/MMM/yyyy h:mm tt").Contains(searchTerm).ToList()

抛出一个异常,因为EF不知道如何转换,而DateTime.ToString()转换为SQL,这是有道理的。

到目前为止,我发现的最佳解决方案来自以下页面:Entity Framework 6 ToString(), formatting (DateTime format), query intercept,其中应答者使用以下函数:SqlFunctions.DatePartDbFunctions.Right生成EF可以执行{ {1}}但是对于我的情况,我现在特别需要格式为Contains(2017年1月20日上午08:22),而我正努力以MMM格式使用月份。

希望有人在那里做了类似的事情,可以帮助我:)

在旁注中,如果还有另一种方法可以通过创建从DbFunctionsSqlFunctions类扩展的我自己的函数来实现,这也可以解决问题。

预先感谢 托德

2 个答案:

答案 0 :(得分:0)

要以MMM格式获得月份,可以使用:

DbFunctions.Left(SqlFunctions.DateName("month", x.BirthDate),3)

最终查询如下:

var users = context.User
   .Where(x =>
        (DbFunctions.Right("0" + SqlFunctions.DatePart("d", x.BirthDate), 2) + "/" //day
            + DbFunctions.Left(SqlFunctions.DateName("month", x.BirthDate), 3) + "/" // month
            + SqlFunctions.DatePart("yyyy", x.BirthDate) + " "
            + DbFunctions.Right("0" + (x.BirthDate.Hour > 12 ? x.BirthDate.Hour % 12 : x.BirthDate.Hour).ToString(), 2) + ":"
            + DbFunctions.Right("0" + SqlFunctions.DatePart("mi", x.BirthDate), 2) + " "
            + (x.BirthDate.Value.Hour > 11 ? "PM" : "AM"))
        .Contains(searchTerm)
    ).ToList();

但是我担心性能。

答案 1 :(得分:0)

如果搜索特定格式的日期列很重要,那么我建议将计算列添加到表中以字符串形式显示日期/时间。像这样的解决方案要提防的是性能。对于较小到中等大小的表/数据库,这是可以接受的,但是您需要监视性能,并避免使用像拐杖这样的技术,因为随着系统的发展,它可能会再次咬住您。

ALTER TABLE Users
ADD COLUMN FormattedBirthDate AS formatDate(BirthDate)

其中formatDate是标量函数:

CREATE FUNCTION formatDate 
(
    @dateTime AS DateTime
)
RETURNS VARCHAR(50)
AS
BEGIN
    DECLARE @result AS VARCHAR(50)

    IF @dateTime IS NULL
      RETURN NULL

    SELECT @result = CAST(DATEPART(dd, @dateTime) AS VARCHAR) + '/' + LEFT(DATENAME(MONTH, @dateTime),3) + '/' + CAST(YEAR(@dateTime) AS VARCHAR) + ' ' + CAST(DATEPART(HOUR, @dateTime) - (12 * CEILING((DATEPART(HOUR, @dateTime) - 12)*.1)) AS VARCHAR(2)) + ':' + RIGHT('00' + CAST(DATEPART(MINUTE,@dateTime) AS VARCHAR(2)),2) + ' ' + CASE WHEN DATEPART(HOUR,@dateTime) >= 12 THEN 'PM' ELSE 'AM' END
    RETURN @result

END

这将根据您指定的内容应用静态格式。难以阅读,并且可能会有一些优化。

这将显示一个名为FormattedBirthDate的新列,您可以在EF中进行映射,尽管您需要采取措施以确保将其视为只读并识别为计算列。我不会在ViewModels等中返回它,仅用于您的搜索。

在用户实体中:

public string FormattedBirthDate { get; private set;}

,并在用户实体类型配置中:

Property(x => x.FormattedBirthDate)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);

这将确保在保存对出生日期的更改后,刷新实体格式化的出生日期。因此需要注意的是,如果您更改生日,格式化的生日将不匹配,直到调用SaveChanges为止。