在LinqToEntities中将字符串转换为日期时间(在查询内)

时间:2012-01-31 19:10:41

标签: c# linq entity-framework

我在表格中有字符串格式的日期,我需要将其与参数进行比较,以检索与给定日期匹配的所有行。我怎样才能做到这一点?我不能使用DateTime.Parse和Convert.ToDateTime。它们都不受支持(我收到错误)。这在Linq中是否可行?或者由于此限制我是否必须为其编写存储过程?

注意:我无法将列的数据类型从varchar更改为DateTime,因为该列还包含其他值,而不仅仅是日期。它是一个通用表,该列可能包含基于其他列中的值的不同类型的值。改变这种设计超出了这个问题的范围。

示例代码(“x”是传递给此方法的日期参数):

    from t1 in Table1
    where EntityFunctions.DiffDays(DateTime.Parse(t1.Value),x) == 0
    select new {t1.Col1, t1.Col2};

更新:如果我使用DateTime.Parse,我会收到错误“LINQ to Entities无法识别方法'System.DateTime Parse(System.String)'方法,并且此方法无法转换为商店表达式。” Convert.ToDateTime也有类似的错误。

5 个答案:

答案 0 :(得分:2)

这很有效。您需要一个Extensionmethod来使dateTime解析安全。之后,您可以在Linq查询中使用该方法的结果。它将从表中获取所有行,因此性能方面可能是一个不太理想的(!)解决方案。它回答了这个问题。

    void Main()
    {
         var stringDates = new List<string> { "2011-13-01", "2011-01-12" };

         DateTime paramDate = new DateTime(2011,01,13);

         var q = from stringDate in stringDates
            let realdate = stringDate.SafeParse()
            where realdate == paramDate
            select new { stringDate, realdate };

         q.Dump();
    }


    static class StringDateParseExt
    {
       public static DateTime SafeParse(this string  any)
        {
          DateTime parsedDate;
          DateTime.TryParseExact(any, 
                "yyyy-dd-MM", 
                System.Globalization.CultureInfo.InvariantCulture , 
                System.Globalization.DateTimeStyles.None, 
                out parsedDate);
          return parsedDate;
        }
    }

答案 1 :(得分:1)

(复制我的评论以粘贴一些示例代码)

如果日期是字符串格式,您是否无法在ToString(大概是DateTime)上应用x,然后进行字符串比较?

由于您正在处理字符串表示,因此您需要处理DateTime透明处理的几个问题,包括:

  • 日期 - 时间格式差异(dd/MM/yyyyMM/dd/yyyy)。
  • 单位数天和月的前导零的存在与否(例如01/01/20111/1/2001)。
  • 年份的两位数或四位数表示(例如01/01/201101/01/11)。
  • 时区偏移。例如,2011-01-01 23:30 -01:00的日期实际上是2011-01-02

如果所有日期都采用美国格式,日期和月份为两位数,四位数年份且没有时区偏移,则下面的示例代码将有效。

from t1 in Table1
where t1.Value.StartsWith(x.ToString(@"MM\/dd\/yyyy"))
select new {t1.Col1, t1.Col2};

修改:替代解决方案:

如果您可以在数据库中定义视图,则可以选择性地将VARCHAR强制转换为DATETIME来规避问题。我假设Value是您的日期列的名称。

SELECT CONVERT(DATE, Value, 101) AS Value, Col1, Col2
FROM Table1
WHERE ISDATE(Value) = 1

然后,在LINQ中,执行简单的DateTime等式检查:

from t1 in Table1
where t1.Value == x.Date
select new {t1.Col1, t1.Col2};

答案 2 :(得分:0)

Linq to SQL确实支持Convert.ToDateTime从String转到DateTime。我不确定实体框架,如果你真的使用它而不是。还有一个带有DateDiff方法的类SqlMethods,您可以使用它来转换为TSQL的DateDiff函数。

Linq to SQL还允许您通过强制转换来转换类型。你不能直接在String和DateTime之间进行转换,但你可以通过首先转换为Object然后转换为DateTime来作弊。 Object转换在转换中被删除,但DateTime转换被转换为TSQL转换操作。

答案 3 :(得分:0)

除了@Douglas关于使用字符串表示的问题,您可以使用string Linq中的DateTime转换为SqlFunctions到实体 DbFunctions课程:

DbFunctions.CreateDateTime(SqlFunctions.DatePart("yy", dateString),
                           SqlFunctions.DatePart("mm", dateString),
                           SqlFunctions.DatePart("dd", dateString),
                           SqlFunctions.DatePart("hh", dateString),
                           SqlFunctions.DatePart("mi", dateString),
                           SqlFunctions.DatePart("ss", dateString));

答案 4 :(得分:-1)

您是否尝试过投射?

Expression<Func<string, DateTime>> expr = s => (DateTime)(object)s;

进一步的网络搜索显示缺少字符串日期转换是EF中缺少的功能。看起来支持一些字符串转换,但不支持日期解析:http://msdn.microsoft.com/en-us/library/dd466166.aspx