Member 13315405 Ответов: 1

Пользовательские хранимые процедуры CRUD сначала используют код


Я использовал подход EF6 code-first в новом проекте, и это было замечательно, но теперь я немного борюсь с тем, как настроить хранимые процедуры CRUD, чтобы некоторые столбцы вычислялись в базе данных.

Процесс (аннотация):
public abstract class Process
{
    public int Id {get; set}
    public int Name {get; set}
    public DateTime CreateDate{get; private set}
    public DateTime UpdateDate{get; private set}

    public virtual ICollection<ProcessContact> Contacts { get; set; }
}

ProcessContact:
public class ProcessContact
{
    public string Name {get; set}
    public string Value {get; set}
}

Процесса:
public class ProcessA: Process
{
    public int A {get; set}
}

Процессb:
public class ProcessB: Process
{
    public int B {get; set}
}

Учитывая 4 класса выше в качестве примера, как я могу в коде EF6-во-первых, настроить сгенерированную хранимую процедуру так, чтобы она могла, например:

-> при вставке процесса установите идентификатор как count(*)+1 и CreateDate = GETUTCTIME()
-> При обновлении ProcessContact установите UpdateDate = GETUTCTIME() в таблице процессов

Спасибо

Что я уже пробовал:

Я смотрел на миграции, но, честно говоря, я немного борюсь с этим.

1 Ответов

Рейтинг:
0

Dave Kreskowiak

Во-первых, EF не генерирует хранимые процедуры. Все делается с помощью обычных операторов SQL.

Далее, ваша идея "count(*) + 1" для генерации значения идентификатора записи нелепа и ухудшается в производительности с течением времени по мере увеличения количества записей. Значения идентификаторов записей должны быть сгенерированы базой данных, а не запрограммированы с помощью формулы. Это довольно легко сделать в EF, так как это просто атрибут для добавления в поле, которое вы используете, например:

public abstract class Process
{
    [Key]
    public int Id {get; set}
    public int Name {get; set}
    public DateTime CreateDate{get; private set}
    public DateTime UpdateDate{get; private set}

    public virtual ICollection<ProcessContact> Contacts { get; set; }
}

или по условности. EF предполагает, что ключ задается именем класса с добавлением к нему "Id" :
public abstract class Process
{
    public int ProcessId {get; set}
    public int Name {get; set}
    public DateTime CreateDate{get; private set}
    public DateTime UpdateDate{get; private set}

    public virtual ICollection<ProcessContact> Contacts { get; set; }
}


Обновить поле datetime можно несколькими различными способами. EF6 может использовать хранимые процедуры для выполнения операций с базой данных. Вы должны написать хранимые процедуры, запечь их в базу данных, а затем рассказать EF, как ее использовать.

Или же вы можете просто установить это поле в своем коде C# и отправить обновление в базу данных, используя обычные SaveChanges в вашем контексте EF.


Member 13315405

Дэйв, спасибо тебе за ответ. Я понимаю накладные расходы на использование count(*) + 1, но в некоторых случаях мне нужно, чтобы число было последовательным, а identity() этого не гарантирует.
Что касается вашего заявления "скажите EF, как его использовать", то это моя проблема ...
Я читал статью, где они используют и sql-файл о миграции для замены сгенерированных EF хранимых процедур, но я пытался сделать это в коде.

Извините за глупые вопросы, но я новичок в этом деле. Что посоветуете ?

Dave Kreskowiak

Вы либо не знаете, что такое хранимая процедура, либо не слушаете.

EF НИКОГДА НЕ ГЕНЕРИРУЕТ ХРАНИМЫЕ ПРОЦЕДУРЫ.

Он генерирует инструкцию SQL для выполнения запросов к базе данных. Отдельные операторы не являются хранимыми процедурами.

Учебник по использованию хранимой процедуры в EF: Использование хранимой процедуры в Entity Framework[^]

Member 13315405

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

Dave Kreskowiak

Хахахаха! Он по-прежнему не генерирует хранимые процедуры. Вы должны предоставить код хранимой процедуры. Затем вы можете использовать EF для создания объекта хранимой процедуры в базе данных. Все, что делает EF, - это помещает то, что вы предоставили, в оболочку инструкции CREATE PROCEDURE или любой другой команды, используемой ядром, в ядре базы данных.

Почему? Потому что EF на самом деле не знает ни хрена о том, как генерировать SQL-оператор. Он строит дерево выражений, которое описывает намерение того, что он хочет сделать. Базовый EF-совместимый поставщик баз данных, поставляемый поставщиком баз данных, преобразует дерево выражений в специфичное для движка представление того, что хочет EF. Для всей хранимой процедуры не существует дерева выражений.

Вы должны предоставить специфичный для движка код хранимой процедуры, спецификации параметров и сопоставления полей в теле инструкции CreateStoredProcedure в EF.