Net Core 3 Mysql Pomelo DateTime Несовместимость - PullRequest
0 голосов
/ 26 апреля 2020

Я хочу получить любые данные между двумя датами с помощью. Net Core 3.1.3 Pomelo.EntityFrameworkCore. MySql v3.1.1

При попытке с C# datetime данные не возвращаются:

SELECT * FROM Availability where (StartDate >= '26.03.2020 00:43:47' And StartDate <= '26.03.2020 00:43:47') or (EndDate <= '26.06.2020 00:43:47' And EndDate <= '26.06.2020 00:43:47')

Но я пытаюсь Mysql datetime возвращает некоторые данные:

SELECT * FROM Availability where (StartDate >= '2020-03-26 00:43:47' And StartDate <= '2020-03-26 00:43:47') or (EndDate <= '2020-06-26 00:43:47' And EndDate <= '2020-06-26 00:43:47')

Мои C# коды:

prop => prop.Availabilities.Any(o => (o.StartDate <= model.StartDate && o.StartDate >= model.StartDate) || (o.EndDate <= model.EndDate && o.EndDate >= model.EndDate))

Что я могу сделать. Net Основные коды?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Посмотрите на следующий код, который демонстрирует, как использовать System.DateTime в EF Core, и работает без проблем:

using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public class IceCream
    {
        public int IceCreamId { get; set; }
        public string Name { get; set; }
        public DateTime BestServedBefore { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<IceCream> IceCreams { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseMySql(
                    "server=127.0.0.1;port=3306;user=root;password=;database=So61433252",
                    b => b.ServerVersion("8.0.20-mysql"))
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<IceCream>()
                .HasData(
                    new IceCream
                    {
                        IceCreamId = 1,
                        Name = "Vanilla",
                        BestServedBefore = DateTime.Today.AddDays(30)
                    },
                    new IceCream
                    {
                        IceCreamId = 2,
                        Name = "Chocolate",
                        BestServedBefore = new DateTime(2020, 5, 1)
                    }
                );
        }
    }

    internal class Program
    {
        private static void Main()
        {
            using (var context = new Context())
            {
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();

                // This code will work with *any* current culture, because EF Core and
                // Pomelo don't use the current culture for DateTime formatting.
                // Demonstrated here by explicitly setting the German culture.
                // This is of course *not necessary* and just for demonstration
                // puroposes.
                Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("de-DE");

                // The following two queries use both, a literal `DATETIME`
                // value and a `System.DateTime` parameter.
                var today = DateTime.Today;

                var badIceCreams = context.IceCreams
                    .Where(i => i.BestServedBefore <= new DateTime(2020, 5, 6) ||
                                i.BestServedBefore <= today)
                    .ToList();

                var isAnyIceCreamBad = context.IceCreams
                    .Any(i => i.BestServedBefore <= new DateTime(2020, 5, 6) ||
                              i.BestServedBefore <= today);

                Debug.Assert(badIceCreams.Count == 1);
                Debug.Assert(badIceCreams[0].IceCreamId == 2);
                Debug.Assert(isAnyIceCreamBad == true);
            }
        }
    }
}

Он генерирует следующие SQL состояний:

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']

      CREATE DATABASE `So61433252`;

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (24ms) [Parameters=[], CommandType='Text', CommandTimeout='30']

      CREATE TABLE `IceCreams` (
          `IceCreamId` int NOT NULL AUTO_INCREMENT,
          `Name` longtext CHARACTER SET utf8mb4 NULL,
          `BestServedBefore` datetime(6) NOT NULL,
          CONSTRAINT `PK_IceCreams` PRIMARY KEY (`IceCreamId`)
      );

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']

      INSERT INTO `IceCreams` (`IceCreamId`, `BestServedBefore`, `Name`)
      VALUES (1, '2020-06-05 00:00:00', 'Vanilla');

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']

      INSERT INTO `IceCreams` (`IceCreamId`, `BestServedBefore`, `Name`)
      VALUES (2, '2020-05-01 00:00:00', 'Chocolate');

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (8ms) [Parameters=[@__today_0='2020-05-06T00:00:00' (DbType = DateTime)], CommandType='Text', CommandTimeout='30']

      SELECT `i`.`IceCreamId`, `i`.`BestServedBefore`, `i`.`Name`
      FROM `IceCreams` AS `i`
      WHERE (`i`.`BestServedBefore` <= '2020-05-06 00:00:00') OR (`i`.`BestServedBefore` <= @__today_0)

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@__today_0='2020-05-06T00:00:00' (DbType = DateTime)], CommandType='Text', CommandTimeout='30']

      SELECT EXISTS (
          SELECT 1
          FROM `IceCreams` AS `i`
          WHERE (`i`.`BestServedBefore` <= '2020-05-06 00:00:00') OR (`i`.`BestServedBefore` <= @__today_0))

Как видите, даже если мы явно установили текущую культуру на de-DE (которая использует формат даты dd.MM.yyyy HH:mm:ss), значение System.DateTime по-прежнему правильно отформатировано с использованием формата yyyy-MM-dd HH:mm:ss:

WHERE (`i`.`BestServedBefore` <= '2020-05-06 00:00:00')

Однако, поскольку вы обычно используете переменные для фильтрации даты, эти переменные будут преобразованы в параметры, поэтому на практике ваши запросы вообще не будут содержать никаких литералов DATETIME, а будут содержать только ссылки на параметры. Это можно увидеть в примере кода с использованием переменной today, которая переводит в следующий фрагмент SQL:

OR (`i`.`BestServedBefore` <= @__today_0)

Наконец, вы можете видеть, что запрос Any() LINQ преобразуется в SELECT EXISTS (SELECT 1 FROM ... WHERE ...) SQL запрос, который отличается от того, который вы указали в своем вопросе.

Похоже, что вы делаете что-то очень неправильное в своем коде.

0 голосов
/ 26 апреля 2020

Как я уже упоминал в комментариях, ваш запрос, скорее всего, не тот, который вы хотите:

prop => prop.Availabilities.Any(o =>
    (o.StartDate <= model.StartDate && o.StartDate >= model.StartDate) ||
    (o.EndDate <= model.EndDate && o.EndDate >= model.EndDate))

Это потребует, чтобы o.StartDate было меньше-равно model.StartDate и o.StartDate должно быть больше-равно model.StartDate. Это фактически означает, что o.StartDate должно быть равно model.StartDate. То же самое относится и к EndDate. Таким образом, эффективный запрос, который вы выполняете, таков:

prop => prop.Availabilities.Any(o =>
    (o.StartDate == model.StartDate) ||
    (o.EndDate == model.EndDate))

Скорее всего, это не то, что вам нужно. Вместо этого, если вы хотите проверить элементы между вашими датами, вы должны сделать это следующим образом:

prop => prop.Availabilities.Any(o =>
    o.StartDate >= model.StartDate && o.EndDate <= model.EndDate)

Так что теперь вы ищите элементы, в которых включен o.StartDate или после model.StartDate и , где o.EndDate включено или до model.EndDate. Это делает model.StartDate и model.EndDate диапазоном, в котором должна соответствовать доступность.

...