DateTime LINQ等式和实体框架未按预期工作

时间:2015-04-30 14:31:48

标签: c# linq entity-framework datetime

我有一个带有DateTime成员的类,我将该类的实例存储到队列中(字节转换),并且我还使用Entity Framework将该实例存储到数据库中。它看起来如下:

// Create instance and set DateTime
MyClass m = new MyClass();
m.CurrentDT = DateTime.Now;

// Store in to database
var db = new EFContext();
db.MyClasses.Add(m);
db.SaveChanges();
db.Dispose();

// Put in to queue
myQueue.Add(m);   // stores as bytes

在某些时候,我将我的对象拉回队列,如下所示:

MyClass mQueueItem = (MyClass)NET.ByteArrayToObject(queueData);

/**
 * Converts a byte array to an object
 */
public static Object ByteArrayToObject(byte[] bytes)
{
    BinaryFormatter formatter = new BinaryFormatter();
    MemoryStream stream = new MemoryStream(bytes);
    object rval = formatter.Deserialize(stream);
    stream.Close();
    return rval;
}

1。不起作用:然后我尝试在我的Entity Framework数据库中找到该确切的实例,但我始终没有从此搜索中返回任何结果:

db.MyClasses.Where(dbItem => dbItem.CurrentDT.Equals(mQueueItem.CurrentDT));

2。不起作用:那么我尝试按如下方式手动浏览每个项目:

foreach(MyClass dbItem in db.MyClasses.ToList())
{
   Console.WriteLine("Is equal: " + dbItem.CurrentDT.Equals(mQueueItem.CurrentDT));
}

...我当然对每个人都是假的,虽然我知道其中一个肯定是我要找的东西。

第3。 Works:执行转换为字符串实际上返回一个项目为true:

foreach(MyClass dbItem in db.MyClasses.ToList())
{
   Console.WriteLine("Is equal: " + dbItem.CurrentDT.ToString().Equals(mQueueItem.CurrentDT.ToString()));
}

4。不起作用:但最后,运行此LINQ查询不会再次返回任何项目:

db.MyClasses.Where(dbItem => dbItem.CurrentDT.ToString().Equals(mQueueItem.CurrentDT.ToString()));

那么我对如何存储DateTime缺少什么以及如何在LINQ中对它运行相等?为什么1或2不工作,但3工作,为什么4不工作?

修改:以下是来自(1)

的查询
SELECT 
[Extent1].[PutInQueue] AS [PutInQueue],   // <--- This is the DateTime
[Extent1].[EmailedFrom] AS [EmailedFrom], 
[Extent1].[POName] AS [POName], 
[Extent1].[FC] AS [FC], 
[Extent1].[POSize] AS [POSize], 
[Extent1].[ExcelFilename] AS [ExcelFilename], 
[Extent1].[ExcelData] AS [ExcelData], 
[Extent1].[PDFFilename] AS [PDFFilename], 
[Extent1].[PDFData] AS [PDFData]
FROM [dbo].[IncomingPOes] AS [Extent1]
WHERE [Extent1].[PutInQueue] = @p__linq__0

以下是(4)的结果查询:

SELECT 
[Extent1].[PutInQueue] AS [PutInQueue],   // <--- This is the DateTime
[Extent1].[EmailedFrom] AS [EmailedFrom], 
[Extent1].[POName] AS [POName], 
[Extent1].[FC] AS [FC], 
[Extent1].[POSize] AS [POSize], 
[Extent1].[ExcelFilename] AS [ExcelFilename], 
[Extent1].[ExcelData] AS [ExcelData], 
[Extent1].[PDFFilename] AS [PDFFilename], 
[Extent1].[PDFData] AS [PDFData]
FROM [dbo].[IncomingPOes] AS [Extent1]
WHERE  CAST( [Extent1].[PutInQueue] AS nvarchar(max)) =  CAST( @p__linq__0 AS nvarchar(max))

编辑:完整代码示例以下是演示此问题的完整代码示例。将对象拉回EF数据库后,DateTimes会使对象失败。

https://github.com/gnychis/DbDateTimeTest

[Serializable]
public class MyClasse
{
    [Key]
    public DateTime dateTime { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<MyClasse> MyClasses { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        // Store it in the queue
        MyClasse original = new MyClasse();
        original.dateTime = DateTime.Now;

        // Store it in the database
        var db = new MyContext();
        db.Database.ExecuteSqlCommand("TRUNCATE TABLE dbo.MyClasses");
        db.MyClasses.Add(original);
        db.SaveChanges();

        // Check the database version
        MyClasse dbItem = db.MyClasses.FirstOrDefault();
        Console.WriteLine("DB Item:");
        Console.WriteLine("  * Original: " + original.dateTime.ToString() + " ... Milliseconds: " + original.dateTime.Millisecond);
        Console.WriteLine("  * DB Item: " + dbItem.dateTime.ToString() + " ... Milliseconds: " + dbItem.dateTime.Millisecond);
        Console.WriteLine("  * Equal? " + dbItem.dateTime.Equals(original.dateTime));

        Console.ReadLine();
    }
}
  

DB Item:

     
      
  • 原文:2015/4/30 1:27:29 ......毫秒:841

  •   
  • DB项目:2015年4月30日下午1:27:29 ......毫秒:843

  •   
  • 等于?假

  •   

2 个答案:

答案 0 :(得分:2)

根据MSDN,日期时间值四舍五入为.000,.003或.007秒的增量。

似乎不建议将DateTime用于新工作。他们建议使用DateTime2,因为它具有更高的精度。

答案 1 :(得分:0)

我认为DateTime的格式有些不同,或者存储的数字不完全匹配。 3是有效的,因为你没有过滤任何东西。我将日期时间存储为小数,其中整数表示从1900年1月1日开始的天数,分数是日期的小数部分。 8小时是8/24 = 1/3,这是重复分数。 DateTime存储为UTC时间,并根据本地时区执行转换。我会仔细查看4中的字符串结果,并验证输入字符串和输出字符串是否完全匹配。