[英]Entity Framework - Oracle - Compare nullable DateTime using linq is not working
[英]DateTime LINQ equality and entity framework not working as expected
我有一個帶有DateTime成員的類,並將該類的實例存儲到隊列中(字節轉換),並且我也使用實體框架將該同一個實例存儲到數據庫中。 看起來如下:
// 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.工作原理:轉換為字符串實際上會返回一項為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();
}
}
數據庫項目:
原文:4/30/2015 1:27:29 PM ...毫秒:841
DB項目:2015/4/30下午1:27:29 ...毫秒:843
等於? 假
根據MSDN ,日期時間值四舍五入為.000,.003或.007秒。
似乎不建議將DateTime用於新工作。 相反,他們建議使用DateTime2,因為它具有更高的精度。
我認為在某些情況下DateTime的格式不同,或者存儲的數字不完全匹配。 3有效,因為您沒有過濾任何東西。 日期時間以小數形式存儲,其中整數表示從1900年1月1日開始的天數,而小數是日期的小數部分。 8小時是8/24 = 1/3,這是重復分數。 DateTime存儲為UTC時間,並根據本地時區執行轉換。 我將仔細查看4中的字符串結果,並驗證輸入字符串和輸出字符串是否完全匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.