我首先使用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.DatePart
和DbFunctions.Right
生成EF可以执行{ {1}}但是对于我的情况,我现在特别需要格式为Contains
(2017年1月20日上午08:22),而我正努力以MMM格式使用月份。
希望有人在那里做了类似的事情,可以帮助我:)
在旁注中,如果还有另一种方法可以通过创建从DbFunctions或SqlFunctions类扩展的我自己的函数来实现,这也可以解决问题。
预先感谢 托德
答案 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为止。