简体   繁体   English

.NET DataRowComparer DateTime与T-SQL DateTime的比较

[英].NET DataRowComparer DateTime Comparison To T-SQL DateTime

I have learned that SQL Server stores DateTime differently than the .NET Framework . 我知道SQL Server 与.NET Framework的存储日期时间不同 This is very unfortunate in the following circumstance: Suppose I have a DataRow filled from my object properties - some of which are DateTime - and a second DataRow filled from data for that object as persisted in SQL Server: 在以下情况下,这是非常不幸的:假设我有一个从对象属性填充的DataRow-其中一些是DateTime-,另一个是从该对象的数据填充的第二个DataRow,该对象保留在SQL Server中:

DataRow drFromObj = new DataRow(itemArrayOfObjProps);
DataRow drFromSQL = // blah select from SQL Server

Using the DataRowComparer on these two DataRows will give an unexpected result: 在这两个DataRows上使用DataRowComparer会产生意外的结果:

// This gives false about 100% of the time because SQL Server truncated the more precise
// DateTime to the less precise SQL Server DateTime
DataRowComparer.Default.Equals(drFromObj, drFromSQL);

My question was going to be, 'How do other people deal with reality in a safe and sane manner?' 我的问题是,“其他人如何安全,理智地处理现实?” I was also going to rule out converting to strings or writing my own DataRowComparer. 我还将排除转换为字符串或编写自己的DataRowComparer的可能性。 I was going to offer that, in absence of better advice, I would change the 'set' on all of my DateTime properties to convert to a System.Data.SqlTypes.SqlDateTime and back upon storage thusly: 我要提供的是,在没有更好建议的情况下,我将更改所有DateTime属性上的“设置”以转换为System.Data.SqlTypes.SqlDateTime并由此恢复存储:

public Nullable<DateTime> InsertDate
{
  get
  {
    if (_InsDate.HasValue)
      return _InsDate;
    else
      return null;
  }

  set
  {
    if (!object.ReferenceEquals(null, value) && value.HasValue)
    _InsDate = (DateTime)(new System.Data.SqlTypes.SqlDateTime(value));
  }
}

I know full well that this would probably get screwed up as I used the _InsDate variable directly somewhere rather than going through the property. 我很清楚,当我直接在某个地方而不是通过属性使用_InsDate变量时,这可能会搞砸。 So my other suggestion was going to be simply using System.Data.SqlTypes.SqlDateTime for all properties where I might want a DateTime type to round trip to SQL Server (and, happily, SqlDateTime is nullable). 因此,我的其他建议是对所有属性使用System.Data.SqlTypes.SqlDateTime,而我可能希望DateTime类型往返于SQL Server(而且,SqlDateTime可为空)。 This post changed my mind, however, and seemed to fix my immediate problem. 这篇文章改变了我的想法,但是,似乎解决了我眼前的问题。 My new question is, 'What are the caveats or real world experiences using the SQL Server datetime2(7) data type rather than the good, old datetime data type?' 我的新问题是,“使用SQL Server datetime2(7)数据类型而不是旧的老式datetime数据类型有什么警告或现实经验?”

TL;DR: Comparing dates is actually hard, even though it looks easy because you get away with it most of the time. TL; DR:比较日期实际上很困难,尽管看起来比较容易,因为您大部分时间都不喜欢它。

You have to be aware of this issue and round both values yourself to the desired precision. 您必须意识到这个问题,并将两个值自己舍入到所需的精度。

This is essentially the same issue as comparing floating point numbers. 这本质上是与比较浮点数相同的问题。 If two times differ by four nanoseconds, does it make sense for your application to consider them different, or the same? 如果两次相差四个纳秒,那么对于您的应用程序来说 ,将它们视为不同还是相同是否有意义?

For example, if two servers have logged the same event, searching for corresponding records, you wouldn't say "no that can't be the correct event because the time is wrong by 200 nanoseconds". 例如,如果两台服务器记录了相同的事件,搜索相应的记录,则不会说“不,那不是正确的事件,因为时间错误了200纳秒”。 Clocks can differ by that amount on two servers no matter how hard they try to keep their time synchronised. 无论两台服务器尝试保持时间同步的努力程度,时钟的差异都可以达到该数量。 You might accept that an event seen on server A and logged with a time a couple of seconds after the time on server B might have been actually seen simultaneously or the other way around. 您可能会接受在服务器A上看到并在服务器B上的时间之后几秒钟记录的事件可能实际上是同时或以其他方式看到的。

Note: 注意:

  • If you are comparing data which is supposed to have made some sort of round-trip out of the database, you may find it has been truncated to the second or minute. 如果您正在比较应该从数据库中进行某种往返的数据,则可能会发现它已被截断至秒或分钟。 (For example if it has been through Excel or an old VB application, or been written to a file and parsed back in.) (例如,如果它是通过Excel或旧的VB应用程序生成的,或者已写入文件并解析回去。)

  • Data originating from external sources is generally rounded to the day, the minute, or the second. 来自外部来源的数据通常会四舍五入到天,分钟或秒。 (except sometimes logfiles, eventlogs or electronic dataloggers, which may have milliseconds or better) (有时日志文件,事件日志或电子数据记录器的时间可能会毫秒或更好,但除外)

  • If the data has come from SQL Server, and you are comparing it back to itself (for example to detect changes), you may not encounter any issues as they will be implicitly truncated to the same precision. 如果数据来自SQL Server,并且正在将其与自身进行比较(例如,检测更改),则可能不会遇到任何问题,因为它们将被隐式地截断为相同的精度。

  • Daylight savings and timezones introduce additional problems. 夏时制和时区会带来其他问题。

  • If searching for dates, use a date range. 如果要搜索日期,请使用日期范围。 And make sure you write the query in such a way that any index can be used. 并确保以可以使用任何索引的方式编写查询。

Somewhat related: 有点相关:

Identity increments. 身份增加。 Sort by Identity and you get insert order. 按身份排序,您将获得插入顺序。 You (can) control insert order. 您(可以)控制插入顺序。

I seriously doubt output would ever by out of order but if you don't trust it you can use @SeeMeSorted 我严重怀疑输出是否会乱序,但是如果您不信任它,可以使用@SeeMeSorted

DECLARE @SeeMeSort TABLE
( [ID] [int] IDENTITY(1,1) NOT NULL,
  [Name] [nvarchar](20) NOT NULL);
DECLARE @SeeMeSorted TABLE
( [ID] [int] primary key  NOT NULL,
  [Name] [nvarchar](20) NOT NULL);
insert into @SeeMeSort ([Name])
OUTPUT INSERTED.[ID], INSERTED.[name]
values ('fff'), ('hhh'), ('ggg');
insert into @SeeMeSort ([Name])
OUTPUT INSERTED.[ID], INSERTED.[name]
  into @SeeMeSorted
values ('xxx'), ('aaa'), ('ddd');
select * from @SeeMeSorted order by [ID];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM