Нужно перебрать коллекцию, и вытащить элемент, дата которого равна заданной.
Пишу LINQ запрос:
manager.VM = DB.FirstOrDefault(x => (x.LaunchTime.CompareTo(chosenvmlauchtime)==0));
Не работает. Пробую последовательно:
manager.VM = DB.FirstOrDefault(x => (x.LaunchTime==chosenvmlauchtime);
manager.VM = DB.FirstOrDefault(x =>(x.LaunchTime.Equals(chosenvmlauchtime));
manager.VM = DB.FirstOrDefault(x =>(Object.Equals(x.LaunchTime, chosenvmlauchtime));
Не работает.
При этом такой монстр:
manager.VM = DB.FirstOrDefault(x => x.LaunchTime.Day==chosenvmlauchtime.Day&&x.LaunchTime.Hour==chosenvmlauchtime.Hour&&x.LaunchTime.Minute==chosenvmlauchtime.Minute&&x.LaunchTime.Second==chosenvmlauchtime.Second);
- работает.
По тому, что нагуглил, должны работать и первые три метода. Но не работают, на выходе null
Что я делаю не так?
Будьте внимательны при сравнении DateTimes, сгенерированных в C#. Структура DateTime в C# имеет более высокую точность, чем тип datetime1 в SQL.
Поэтому, если вы создаете DateTime в C# (скажем, из DateTime.Now), сохраните его в базе данных и верните обратно, это, скорее всего, будет отличаться.
2017.07.07 12:28:23.6115968
2017.07.07 12:28:23.6100000
Когда происходит сравнение двух значений DateTime
для того что бы мы получили true
два объекта должны быть полностью равны вплоть до DateTime.Ticks
, которые представляют число тактов, представляющих дату и время данного экземпляра.
Один такт соответствует 100 наносекундам или одной десятимиллионной секунде. Существует 10 000 тактов в миллисекунде или 10 миллионов тактов в секунде.
Для того что бы понять насколько это быстро, можно провести следующий эксперимент. Создайте последовательно две переменные DateTime
и посмотрите значение Ticks
. Несмотря на то, что переменные создаются одна за другой количество тактов у них будет разным.
var ticks1 = DateTime.Now.Ticks; // 636350607119477684
var ticks2 = DateTime.Now.Ticks; // 636350607212468695
Итак, вроде как разобрался. Спасибо ответившим, особенно user270576, который натолкнул меня на правильный путь.
Проект сделан на EntityFramework code-first. Базу тоже генерил EF. По умолчанию, он ставит тип данных datetime, и в результате, при преобразовании в тип DateTime
C# теряется часть данных. Проблема была решена принудительной сменой типа данных в БД на datetime2
. После чего заработали и ручной метод с миллисекундами, и стандартные методы. Принудительную смену типа провел через fluentAPI добавлением в метод файла- наследника DBContext
. Как-то можно через атрибуты непосредственно в модели, но у меня не получилось.
код метода в файле контекста:
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
base.OnModelCreating(modelbuilder);
modelbuilder.Entity<SiteInfo>().
Property(p => p.LaunchTime)
.HasColumnType("datetime2")
.HasPrecision(0)
.IsRequired();
}
ЗЫ: для коллег-начинающих: не забудьте после изменений выполнить в Консоли диспетчера пакетов команды Add-Migration [name]
и Upgrade-Database -Verbose
для обновления БД.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Недавно рыскал по object browser'у, и увидел такую картину
Хочу написать програмулину чтобы блокировала все сетевые порты:) этак вирус для начальникаПусть сидит на одном ftp и без танчиков