Я работаю над переносом нашей модели на EF Core, и у меня возникают проблемы с поиском способа вызова следующего кода:

InitializeTime = context.ExecuteSqlCommand<DateTime>("SELECT CURRENT_TIMESTAMP FROM DUAL").FirstOrDefault();

Мы используем время базы данных для синхронизации всего, но из того, что я могу найти, вызов необработанного sql вне DbSet недоступен, а тип возвращаемого значения ограничен аргументом типа DbSet.

Я осмотрелся и обнаружил, что есть DbQuery объекты (статья), но это кажется тяжелой работой, чтобы получить текущую системную дату и время.

Кто-нибудь еще сталкивался с этим и нашел более простое решение?

Примечание: это настольное приложение, поэтому код будет работать на стороне клиента, а системная дата и время не будут надежными.

0
Felix Castor 28 Фев 2020 в 18:08

2 ответа

Лучший ответ

На случай, если кто-то столкнется с той же проблемой. Я закончил со следующим:

Создайте новый класс, содержащий свойство DateTime

public class SystemDateTime
{
    /// <summary>
    /// System datetime from the server.
    /// </summary>
    public DateTime DateTime { get; set; }
}

Добавьте DbSet типа SystemDateTime в модель

    /// <summary>
    /// Set for getting the current date time from the database.
    /// </summary>
    public DbSet<SystemDateTime> SystemDateTimes { get; set; }

Примечание. В EFCore 3.1 он должен быть типа DbSet, но в EFCore 2.? есть другой тип, посвященный этому виду набора, называемый DbQuery. См. Статью with-entity-types "rel =" nofollow noreferrer "> Здесь .

Добавьте сопоставление в конструктор моделей .

modelBuilder.Entity<SystemDateTime>().HasNoKey();
modelBuilder.Entity<SystemDateTime>().Property<DateTime>(x => x.DateTime).HasColumnName(@"DateTime").HasColumnType(@"TIMESTAMP").IsRequired().ValueGeneratedNever();

Используйте DbSet FromSqlRaw для запроса к базе данных

List<SystemDateTime> systemDateTime = context.SystemDateTimes.FromSqlRaw("SELECT TO_CHAR (SYSDATE, 'MM-DD-YYYY HH24:MI:SS') \"DateTime\" FROM DUAL").ToList();

Это вернет список из одного элемента, поэтому используйте First() или Single, чтобы получить необходимое значение.

1
Felix Castor 3 Мар 2020 в 15:07

Тезки EFCore context.Database.ExecuteSqlRaw(sql) / context.Database.ExecuteSqlRInterpolated(sql) (или context.Database.ExecuteSqlCommand(sql) до EFCore 3, вы не указали, с какой версией вы работаете) могут только вернуть int, количество строк, затронутых выполнением оператора sql.

context.Query<TQuery>() (до EFCore 3, устарело от EFCore 3 и далее) или объект без ключа (EFCore 3 и далее), поддерживаемый обычным POCO, - это ваши варианты, насколько я знаю, если вы хотите использовать EFCore для выполнения запроса ,

Типы сущностей без ключей doco:

Сценарии использования

Вот некоторые из основных сценариев использования для типов объектов без ключа:

Служит типом возврата для необработанных запросов SQL.

С точки зрения накладных расходов, это не совсем так, когда вы думаете с точки зрения шаблона единицы работы / хранилища, который реализует EFCore; По сути, это заставляет вас создавать хранилище, а не выполнять специальные запросы по всему месту.

1
rgvlee 1 Мар 2020 в 12:20