EF.Toolkits.CustomSql 1.0.13-alpha

This is a prerelease version of EF.Toolkits.CustomSql.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package EF.Toolkits.CustomSql --version 1.0.13-alpha                
NuGet\Install-Package EF.Toolkits.CustomSql -Version 1.0.13-alpha                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EF.Toolkits.CustomSql" Version="1.0.13-alpha" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add EF.Toolkits.CustomSql --version 1.0.13-alpha                
#r "nuget: EF.Toolkits.CustomSql, 1.0.13-alpha"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install EF.Toolkits.CustomSql as a Cake Addin
#addin nuget:?package=EF.Toolkits.CustomSql&version=1.0.13-alpha&prerelease

// Install EF.Toolkits.CustomSql as a Cake Tool
#tool nuget:?package=EF.Toolkits.CustomSql&version=1.0.13-alpha&prerelease                

EF.Toolkits

Данный проект содержит библиотеки для расширения возмжностей EF Core

Регистрация

optionsBuilder
    .UseNpgsql("Host=localhost;Port=5432;Database=EF.Toolkits.Tests;Username=postgres;Password=****")
    .UseCustomSql(options => options.UseTriggers())
    .UseAutoComments("Comments.xml");

EF.Toolkits.AutoComments

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

    <PropertyGroup>
        <GenerateDocumentationFile>true</GenerateDocumentationFile>
        <DocumentationFile>Comments.xml</DocumentationFile>
    </PropertyGroup>

Также поддерживается описание значений Enum через атрибут AutoCommentsEnumValues или с использованием настройки AddEnumValuesComments

            optionsBuilder
                .UseAutoComments(options => options.WithXmlPaths("Comments.xml").AddEnumValuesComments());

Для того, чтобы исключить описание значений Enum можно использовать атрибут IgnoreAutoCommentsEnumValues Пример: Для перечисления AnimalType будет создан такой комментарий: Тип.\n\n0 - Собакен.\n1 - Кошька.\n2 - Рыбка.\n3 - Другое.

    /// <summary>
    /// Тип живтоного.
    /// </summary>
    public enum AnimalType
    {
        /// <summary>
        /// Собакен.
        /// </summary>
        Dog,

        /// <summary>
        /// Кошька.
        /// </summary>
        Cat,

        /// <summary>
        /// Рыбка.
        /// </summary>
        Fish,

        /// <summary>
        /// Другое.
        /// </summary>
        Other
    }

EF.Toolkits.CustomSql

Добавляет возможность автоматически добавлять пользовательский SQL в код миграции с поддержкой изменения. Для каждого пользовательского SQL необхдимо определить 2 скрипта: на создание (Up) и на удаление (Down). Соответствующие скрипты попадут в файл миграции. В начало ммиграции добавляются скрпты для удаления, в конце миграции на добавление.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .AddCustomSql("animals_view", "SELECT * FROM animals a WHERE a.type = 1", "DROP VIEW  IF EXISTS animals_view");
}

Чтобы автоматически обновлять свои SQL скрипты при обновлении модели можно использовать класс CustomSqlGenerator, который имеет полезные функции для получения имени столбца и таблицы.

Пример:

Создаем класс TriggersGenerator в котором описываем свои SQL:

    public class TriggersGenerator : CustomSqlGenerator
    {
        public TriggersGenerator(DbContext dbContext, ModelBuilder modelBuilder) : base(dbContext, modelBuilder)
        {
        }

        public string GenerateTriggersScript()
        {
            var animal = GetTableName<Animal>();

            var species = GetColumnName<Animal>(x => x.Species);
            var animalType = GetColumnName<Animal>(x => x.AnimalType);

            return
                $"IF NEW.{species} IS NOT NULL AND NEW.{species} IS DISTINCT FROM OLD.{species} THEN\n" +
                $"    RAISE EXCEPTION 'Нельзя менять породу';\n" +
                $"END IF;\n" +
                $"IF NEW.{species} IS NOT NULL THEN\n" +
                $"    UPDATE {animal} SET {animalType} = NEW.{animalType}\n" +
                $"    WHERE {species} = NEW.{species};\n" +
                $"END IF;";
        }
    }

И используем его в OnModelCreating(ModelBuilder modelBuilder)

            modelBuilder.Entity<Animal>(entity =>
            {
                var triggersGenerator = new TriggersGenerator(this, modelBuilder);

                entity.BeforeInsertOrUpdate("before_insert_or_update", triggersGenerator.GenerateTriggersScript());
            });

Если поля Species, AnimalType будут переименованы в БД, то при создании миграции будут обновлены ваши SQL.

EF.Toolkits.CustomSql.Triggers.Postgresql

Провайдер для автоматического добавления триггеров. Зависит от EF.Toolkits.CustomSql

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Figure>(entity =>
   {
       entity.BeforeInsert("set_square", "new.square = 0");

       entity.BeforeUpdate("prevent_update_with_negative_square", "IF new.square < 0 THEN raise exception 'square negative' END IF;");
    });
}

Поддерживаются операции Insert, Update, Delete, InsertOrUpdate с временем выполнения триггера Before, After, Instead

Вам нужно только определить тело триггера, всё остальное сделает библиотека

Пример файла миграции

    public partial class Initial : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql("SELECT * FROM \"Animals\" a WHERE a.\"AnimalType\" = 1");

            migrationBuilder.Sql("CREATE FUNCTION before_insert_or_update() RETURNS trigger as $before_insert_or_update$\r\nBEGIN\r\nIF NEW.\"Species\" IS NOT NULL AND NEW.\"Species\" IS DISTINCT FROM OLD.\"Species\" THEN\n    RAISE EXCEPTION 'Нельзя менять породу';\nEND IF;\nIF NEW.\"Species\" IS NOT NULL THEN\n    UPDATE \"Animals\" SET \"AnimalType\" = NEW.\"AnimalType\"\n    WHERE \"Species\" = NEW.\"Species\";\nEND IF;\r\nRETURN NEW;\r\nEND;\r\n$before_insert_or_update$ LANGUAGE plpgsql;\r\n\r\nCREATE TRIGGER before_insert_or_update BEFORE INSERT OR UPDATE\r\nON \"Animals\"\r\nFOR EACH ROW EXECUTE PROCEDURE before_insert_or_update();\r\n");

            migrationBuilder.Sql("CREATE FUNCTION prevent_update_with_negative_square() RETURNS trigger as $prevent_update_with_negative_square$\r\nBEGIN\r\nIF new.square < 0 THEN raise exception 'square negative'; END IF;\r\nRETURN NEW;\r\nEND;\r\n$prevent_update_with_negative_square$ LANGUAGE plpgsql;\r\n\r\nCREATE TRIGGER prevent_update_with_negative_square BEFORE UPDATE\r\nON \"Figures\"\r\nFOR EACH ROW EXECUTE PROCEDURE prevent_update_with_negative_square();\r\n");

            migrationBuilder.Sql("CREATE FUNCTION set_square() RETURNS trigger as $set_square$\r\nBEGIN\r\nnew.square = 0;\r\nRETURN NEW;\r\nEND;\r\n$set_square$ LANGUAGE plpgsql;\r\n\r\nCREATE TRIGGER set_square BEFORE INSERT\r\nON \"Figures\"\r\nFOR EACH ROW EXECUTE PROCEDURE set_square();\r\n");
               }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.Sql("DROP VIEW  IF EXISTS animals_view");

            migrationBuilder.Sql("DROP FUNCTION before_insert_or_update() CASCADE;");

            migrationBuilder.Sql("DROP FUNCTION prevent_update_with_negative_square() CASCADE;");

            migrationBuilder.Sql("DROP FUNCTION set_square() CASCADE;");
        }
    }
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on EF.Toolkits.CustomSql:

Package Downloads
EF.Toolkits.CustomSql.Triggers

Managing the creation of triggers in the database via the EF migrations.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.16-alpha 36 11/20/2024
1.0.15-alpha 107 10/24/2024
1.0.14-alpha 36 10/24/2024
1.0.13-alpha 40 10/24/2024
1.0.12-alpha 120 10/18/2024
1.0.11-alpha 36 10/17/2024
1.0.10-alpha 50 10/16/2024
1.0.9-alpha 41 10/14/2024
1.0.8-alpha 44 10/14/2024
1.0.7-alpha 42 10/14/2024
1.0.5-alpha 47 10/14/2024
1.0.4-alpha 52 10/12/2024
1.0.3-alpha 52 10/12/2024
1.0.2-alpha 47 10/12/2024
1.0.1-alpha 53 10/12/2024

Adding Custom SQL via DbContext Model Configuration