Избегайте двойных кавычек при запросе таблиц Oracle, созданных с помощью EF Core 8 Code First

Фон

У меня есть такая модель стола:

public class Book
{
    [Key]
    public Guid Id { get; set; }
    public string Name { get; set; } = default!;
    public string Author { get; set; } = default!;
    public int Pages { get; set; } = default!;
}

Если я запустил команду добавления миграции

dotnet ef migrations add AddBooks -p .\MyApplication.Infrastructure\ -s .\MyApplication.API\

Я получаю ожидаемый результат:

migrationBuilder.CreateTable(
    name: "Books",
    columns: table => new
    {
        Id = table.Column<Guid>(type: "RAW(16)", nullable: false),
        Name = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
        Author = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
        Pages = table.Column<int>(type: "NUMBER(10)", nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Books", x => x.Id);
    });

Если я затем обновлю базу данных:

dotnet ef database update -p .\MyApplication.Infrastructure\ -s .\MyApplication.API\

Таблица создается, как указано:

Где все идет не так

Я ожидаю увидеть, что могу запросить свою таблицу следующим образом:

select * from Books b

Однако там указано, что Table or view does not exist.

Если я создаю свой запрос, он делает это следующим образом:

select * from "Books" b

Это работает правильно, но отличается от того, как настроены все остальные таблицы.

Мой вопрос

Как я могу создать свои таблицы без необходимости использования этих дополнительных двойных кавычки?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Oracle чувствителен к регистру. Однако по умолчанию все идентификаторы, не заключенные в кавычки, преобразуются в верхний регистр, чтобы они выглядели нечувствительными к регистру. Поэтому:

select * from Books
select * from books
select * from BoOkS
select * from BOOKS

Все они будут выбраны из таблицы под названием BOOKS (заглавные буквы) и эквивалентны.

Идентификаторы в кавычках используются для обеспечения учета регистра в идентификаторе. Поэтому:

select * from "Books"
select * from "books"
select * from "BoOkS"
select * from "BOOKS"

Будет выбирать из четырех разных таблиц — Books, books, BoOkS и BOOKS соответственно, и только последний запрос является эквивалентом запросов с использованием идентификаторов без кавычек.


Когда вы создаете миграцию, вы создаете таблицу с именем Books (в смешанном регистре). Это означает, что если вы хотите получить к ней доступ, вам нужно будет использовать идентификатор в кавычках с точным регистром:

select * from "Books"

Альтернативно вам необходимо изменить код EF, чтобы при миграции генерировались идентификаторы в верхнем регистре:

[Table("BOOKS")]
public class Book
{
    [Key]
    [Column("ID")]
    public Guid Id { get; set; }
    [Column("NAME")]
    public string Name { get; set; } = default!;
    [Column("AUTHOR")]
    public string Author { get; set; } = default!;
    [Column("PAGES")]
    public int Pages { get; set; } = default!;
}

Тогда вы сможете использовать идентификаторы без кавычек (в любом случае) в своих запросах.

В противном случае посмотрите, есть ли параметр миграции, который изменит регистр всех идентификаторов на верхний регистр, чтобы вы могли использовать идентификаторы без кавычек.

Приложение

Если вы добавите пакет nuget

EFCore.NamingConventions

в проект, который содержит ваш DbContext и переопределить OnConfiguring, вы можете сделать следующее:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseUpperSnakeCaseNamingConvention();

    base.OnConfiguring(optionsBuilder);
}

Это приведет к созданию таблицы Books следующим образом:

migrationBuilder.CreateTable(
    name: "BOOKS",
    columns: table => new
    {
        ID = table.Column<Guid>(type: "RAW(16)", nullable: false),
        NAME = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
        AUTHOR = table.Column<string>(type: "NVARCHAR2(2000)", nullable: false),
        PAGES = table.Column<int>(type: "NUMBER(10)", nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_BOOKS", x => x.ID);
    });

Это было легко... Я бы предпочел настройку миграции, а не необходимость аннотировать все вручную. Я пока воздержусь от ответа в надежде, что кто-то (или вы) сможет предоставить эту информацию. (Если это займет слишком много времени, я просто приму)

kbd 22.05.2024 10:41

@kbd Я не знаю ответа на настройки миграции, однако, если вы посмотрите документацию Использование операции миграции, там приведен пример того, как переопределить сгенерированный SQL, и пример включает строку .Append(sqlHelper.DelimitIdentifier(operation.Name)), если это был изменен на .Append(operation.Name), тогда сгенерированный запрос будет использовать идентификаторы без кавычек (но также может быть уязвим для SQL-инъекций). ...

MT0 22.05.2024 10:46

Вам необходимо выяснить, возможно ли что-то подобное для таблиц (и понять последствия).

MT0 22.05.2024 10:46

Я нашел это. Я отредактировал ваш ответ, чтобы иметь единственное решение.

kbd 22.05.2024 10:55

@kbd Я просто добавлял что-то подобное, однако ваше редактирование было немного более полным.

MT0 22.05.2024 10:57

Другие вопросы по теме