LINQ实体框架4.2日期时间比较失败

时间:2012-02-09 02:51:07

标签: linq datetime frameworks entity equality

Followind描述了我使用EF 4.2和LINQ遇到的问题。我已经在多个系统上尝试了这个,以及64种和32种二进制文件中的多种SQL(SQL Express和SQL 2008 R2 Sp1),VS 2010 Pro和Premium,都使用调试器,并尝试直接运行二进制文件。我想知道我遇到了什么,如果它是EF的一个问题,或者更可能是我的代码问题而且我错过了与LINQ或EF相关的一些细微差别。任何帮助都会非常感激,已经有6个小时了,我的Google JuJu还不够强大。

我有一个名为session的简单模型,由ID(Guid),Name(String)和Timestamp(DateTime)组成。我能够向dbcontext添加一个会话,并在调试中验证会话记录确实存储在数据库中。用于创建会话对象的时间戳存储在本地变量中,并在存储后立即尝试将会话检索到会话对象的新实例中。检索会话的代码(LINQ)抛出'System.InvalidOperationException“Sequence不包含带有以下stacktrace的元素”:

at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__0[TResult](IEnumerable`1 sequence)
at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.First[TSource](IQueryable`1 source)
at efwtf.Program.Main(String[] args) in d:\vs2010\efwtf\efwtf\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

我能够在调试器中深入查看ctx.Sessions,并在结果集中看到我尝试检索的会话确实存在,如果我遍历结果集并手动比较我可以提取的两个时间戳会议按预期进行。如果我运行代码并为之前运行中添加到数据库的记录传递时间戳值,则它可以正常工作。我可以找到解决方法,最糟糕的情况下,可能会将数据类型更改为字符串,但它让我觉得这不起作用,我假设,这可能是问题的一部分,应该支持该功能。代码如下。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.Entity;
    using System.ComponentModel.DataAnnotations;

    namespace efwtf
    {
       class Program
       {
          static void Main ( string[] args )
          {
             Context ctx = new Context ();
             DateTime ts = DateTime.UtcNow;
             Session s1 = new Session () { Id = Guid.NewGuid(), Name = "Testing", TimeStamp = ts };
             ctx.Sessions.Add ( s1 );
             ctx.SaveChanges ();

             Session s2 = ( from s in ctx.Sessions
                            where ( s.Name == "Testing" && s.TimeStamp.Equals ( ts ) )
                            select s ).First ();

             Console.WriteLine ( s2.Name, s2.TimeStamp );
          }
       }

       class Context : DbContext
       {
          public DbSet<Session> Sessions { get; set; }
       }

       class Session
       {
          [Key]
          public Guid Id { get; set; }
          public string Name { get; set; }
          public DateTime TimeStamp { get; set; }
       }
    }

我在LINQ语句中尝试过各种变体,包括s.datetime.equals(ts)和datetime.compare(s.datetime,ts)== 0,但每次抛出相同的异常。

有人有什么想法吗?那是我吗?这段代码会让我的二进制文件看起来很大= ^)

提前致谢

2 个答案:

答案 0 :(得分:1)

查看以下代码,它有效!然而,它的工作方式是不合逻辑的。因为如果查看note1和note2值,您会看到日期值已正确保存,但未在查询中应用。

var date = new DateTime(ts.Year, ts.Month, ts.Day, ts.Hour, ts.Minute, ts.Second, ts.Millisecond);
Session s2 = (from s in ctx.Sessions
            where (s.Name == "Testing" && s.TimeStamp == date)
            select s).First();

var note1 = s2.TimeStamp == date;
var note2 = s2.TimeStamp == ts;

我猜这是与Entity Framework如何将值分配给@p_ linq _0参数有关的错误。这是我追踪的查询,但我找不到分配给@p_ linq _0的值。

SELECT TOP (1) 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
[Extent1].[TimeStamp] AS [TimeStamp]
FROM [dbo].[Sessions] AS [Extent1]
WHERE (N'Testing' = [Extent1].[Name]) AND ([Extent1].[TimeStamp] = @p__linq__0)

答案 1 :(得分:1)

为了使其工作,我将TimeStamp的数据列修改为数据库中的DateTime2数据类型,如下所示。

class Session 
{ 
   [Key] 
   public Guid Id { get; set; } 
   public string Name { get; set; } 

   [Column(TypeName = "datetime2")]
   public DateTime TimeStamp { get; set; } 
} 

最终认为这是一个解决方案,因为问题似乎在某种程度上与LINQ有关,但是它帮助我克服了障碍并且认为我会发布此处以防万一其他人遇到此问题。