All Projects → win7user10 → Laraue.EfCoreTriggers

win7user10 / Laraue.EfCoreTriggers

Licence: MIT license
Library for writing triggers in C# using package EFCore

Programming Languages

C#
18002 projects

Projects that are alternatives of or similar to Laraue.EfCoreTriggers

EasyProfiler
This repo, provides query profiler for .Net
Stars: ✭ 99 (+94.12%)
Mutual labels:  efcore
MADE.NET
MADE.NET is a home to all of those bits of code that you know you'll reuse in another project. Making app development easier with .NET.
Stars: ✭ 75 (+47.06%)
Mutual labels:  efcore
QuerySpecification
Abstract package for building query specifications in your domain model.
Stars: ✭ 18 (-64.71%)
Mutual labels:  efcore
EFCore.VisualBasic
Adds VB design-time support to EF Core
Stars: ✭ 20 (-60.78%)
Mutual labels:  efcore
django-aws-eb-deploy
This is a GitHub action for automated deployment of Django projects to aws elastic beanstalk.
Stars: ✭ 24 (-52.94%)
Mutual labels:  triggers
SapientGuardian.EntityFrameworkCore.MySql
MySQL database provider for Entity Framework Core
Stars: ✭ 54 (+5.88%)
Mutual labels:  efcore
LYM.NetCore
IdentityServer4+EFCore
Stars: ✭ 17 (-66.67%)
Mutual labels:  efcore
bitbucket-push-and-pull-request-plugin
Plugin for Jenkins v2.138.2 or later, that triggers job builds on Bitbucket's push and pull request events.
Stars: ✭ 47 (-7.84%)
Mutual labels:  triggers
ENLOCK
Efcore with no lock extention
Stars: ✭ 25 (-50.98%)
Mutual labels:  efcore
EFSqlTranslator
A standalone linq to sql translator that can be used with EF and Dapper.
Stars: ✭ 51 (+0%)
Mutual labels:  efcore
SilkierQuartz
SilkierQuartz can host jobs using HostService and Provide a web management tools for Quartz !
Stars: ✭ 263 (+415.69%)
Mutual labels:  triggers
EntityFrameworkCore.Triggered
Triggers for EFCore. Respond to changes in your DbContext before and after they are committed to the database.
Stars: ✭ 361 (+607.84%)
Mutual labels:  efcore
EfCoreJsonValueConverter
JSON ValueConverter for EF Core 3.0+
Stars: ✭ 85 (+66.67%)
Mutual labels:  efcore
mysql-interview-questions
SQL Basics
Stars: ✭ 202 (+296.08%)
Mutual labels:  triggers
SQL-ProcBench
SQL-ProcBench is an open benchmark for procedural workloads in RDBMSs.
Stars: ✭ 26 (-49.02%)
Mutual labels:  triggers
django-pgtrigger
Write Postgres triggers for your Django models
Stars: ✭ 385 (+654.9%)
Mutual labels:  triggers
eShopOnWeb
Sample ASP.NET Core 6.0 reference application, powered by Microsoft, demonstrating a layered application architecture with monolithic deployment model. Download the eBook PDF from docs folder.
Stars: ✭ 8,250 (+16076.47%)
Mutual labels:  efcore
cash-flow
Application for managing cash flows written in ASP.NET Core 6 and Angular 13 (EF Core, Apollo, GraphQL, CQRS)
Stars: ✭ 27 (-47.06%)
Mutual labels:  efcore
Nebula.Admin
Destiny.Core.Flow是基于.Net Core,VUE前后分离,开发的一个开源Admin管理框架目前有以下模块:菜单管理、用户管理、角色管理、用户角色、角色权限等功能。
Stars: ✭ 254 (+398.04%)
Mutual labels:  efcore
Milvasoft
Helper structures for .Net 6 projects.
Stars: ✭ 24 (-52.94%)
Mutual labels:  efcore

Entity Framework Core Triggers

EfCoreTriggers is the library to write native SQL triggers using EFCore model builder. Triggers are automatically translating into sql and adding to migrations.

latest version latest version

Installation

EfCoreTriggers common package is available on Nuget. Version 6.x.x is compatible with EFCore 6.x.x and targets .NET6, 5.x.x intended for EFCore 5.x.x and targets .NET standard 2.1. Install the provider package corresponding to your target database. See the list of providers in the docs for additional databases.

Configuring DB to use triggers

dotnet add package Laraue.EfCoreTriggers.PostgreSql
dotnet add package Laraue.EfCoreTriggers.MySql
dotnet add package Laraue.EfCoreTriggers.SqlServer
dotnet add package Laraue.EfCoreTriggers.SqlLite

Basic usage

The library has extensions for EntityBuilder to configure DbContext.

After update Transaction entity, update records in the table with UserBalance entities.

modelBuilder.Entity<Transaction>()
    .AfterUpdate(trigger => trigger
        .Action(action => action
            .Condition((transactionBeforeUpdate, transactionAfterUpdate) => transactionBeforeUpdate.IsVeryfied && transactionAfterUpdate.IsVeryfied) // Executes only if condition met 
            .Update<UserBalance>(
                (transactionBeforeUpdate, transactionAfterUpdate, userBalances) => userBalances.UserId == oldTransaction.UserId, // Will be updated entities with matched condition
                (oldTransaction, updatedTransaction, oldBalance) => new UserBalance { Balance = oldBalance.Balance + updatedTransaction.Value - oldTransaction.Value }))); // New values for matched entities.

After insert Transaction entity, upsert record in the table with UserBalance entities.

modelBuilder.Entity<Transaction>()
    .AfterDelete(trigger => trigger
        .Action(action => action
            .Condition(deletedTransaction => deletedTransaction.IsVeryfied)
            .Upsert(
                deletedTransaction => new UserBalance { UserId = deletedTransaction.UserId }, // If this field will match more than 0 rows, will be executed update operation for these rows else insert
                deletedTransaction => new UserBalance { UserId = deletedTransaction.UserId, Balance = deletedTransaction.Value }, // Insert, if value didn't exist
                (deletedTransaction, oldUserBalance) => new UserBalance { Balance = oldUserBalance.Balance + deletedTransaction.Value }))); // Update all matched values

After delete Transaction entity, execute raw SQL. Pass deleted entity fields as arguments.

modelBuilder.Entity<Transaction>()
    .AfterDelete(trigger => trigger
        .Action(action => action
            .ExecuteRawSql("PERFORM recalc_balance({0}, {1})"), deletedEntity => deletedEntity.UserId, deletedEntity => deletedEntity.Amount)));

All available triggers

Trigger PostgreSql SQL Server SQLite MySQL
Before Insert + - + +
After Insert + + + +
Instead Of Insert + + + -
Before Update + - + +
After Update + + + +
Instead Of Update + + + -
Before Delete + - + +
After Delete + + + +
Instead Of Delete + + + -

Available actions after trigger has worked

  • Insert
  • InsertIfNotExists
  • Update
  • Upsert
  • Delete
  • ExecuteRawSql

Laraue.EfCoreTriggers.PostgreSql

latest version latest version

Basic usage

var options = new DbContextOptionsBuilder<TestDbContext>()
    .UseNpgsql("User ID=test;Password=test;Host=localhost;Port=5432;Database=test;")
    .UsePostgreSqlTriggers()
    .Options;

var dbContext = new TestDbContext(options);

Laraue.EfCoreTriggers.MySql

latest version latest version

Basic usage

var options = new DbContextOptionsBuilder<TestDbContext>()
    .UseMySql("server=localhost;user=test;password=test;database=test;", new MySqlServerVersion(new Version(8, 0, 22))))
    .UseMySqlTriggers()
    .Options;

var dbContext = new TestDbContext(options);

Laraue.EfCoreTriggers.SqlServer

latest version latest version

Basic usage

var options = new DbContextOptionsBuilder<TestDbContext>()
    .UseSqlServer("Data Source=(LocalDb)\\v15.0;Database=test;Integrated Security=SSPI;")
    .UseSqlServerTriggers()
    .Options;

var dbContext = new TestDbContext(options);

Laraue.EfCoreTriggers.SqlLite

latest version latest version

Basic usage

var options = new DbContextOptionsBuilder<TestDbContext>()
    .UseSqlite("Filename=D://test.db")
    .UseSqlLiteTriggers()
    .Options;

var dbContext = new TestDbContext(options);

Customization

Any service using for generation SQL can be replaced.

private class CustomDbSchemaRetriever : EfCoreDbSchemaRetriever
{
    public CustomDbSchemaRetriever(IModel model) : base(model)
    {
    }

    protected override string GetColumnName(Type type, MemberInfo memberInfo)
    {
        // Change strategy of naming some column
        return 'c_' + base.GetColumnName(type, memberInfo);
    }
}

Adding this service to the container

var options = new DbContextOptionsBuilder<TestDbContext>()
    .UseNpgsql("User ID=test;Password=test;Host=localhost;Port=5432;Database=test;")
    .UsePostgreSqlTriggers(services => services.AddSingleton<IDbSchemaRetriever, CustomDbSchemaRetriever>)
    .Options;

var dbContext = new TestDbContext(options);

Adding translation of some custom function into sql code

To do this thing a custom function converter should be added to a provider

Let's image that we have an extension like

public static class StringExtensions
{
    public static bool Like(this string str, string pattern)
    {
        // Some code
    }
} 

Now a custom converter should be written to translate this function into SQL

public abstract class StringExtensionsLikeConverter : MethodCallConverter
{
    public override bool IsApplicable(MethodCallExpression expression)
    {
        return expression.Method.ReflectedType == typeof(SomeFunctions) && MethodName == nameof(CustomFunctions.Like);
    }
    
    public override SqlBuilder BuildSql(BaseExpressionProvider provider, MethodCallExpression expression, Dictionary<string, ArgumentType> argumentTypes)
    {
        // Generate SQL for arguments, they can be SQL expressions
        var argumentSql = provider.GetMethodCallArgumentsSql(expression, argumentTypes)[0];

        // Generate SQL for this context, it also can be a SQL expression
        var sqlBuilder = provider.GetExpressionSql(expression.Object, argumentTypes);
        
        // Combine SQL for object and SQL for arguments
        // Output will be like "thisValueSql LIKE 'passedArgumentValueSql'"
        return new(sqlBuilder.AffectedColumns, $"{sqlBuilder} LIKE {argumentSql}");
    }
}

All custom converters should be added while setup a database

var options = new DbContextOptionsBuilder<TestDbContext>()
    .UseSqlite("Filename=D://test.db")
    .UseSqlLiteTriggers(services => services.AddMethodCallConverter(converter))
    .Options;

var dbContext = new TestDbContext(options);

Now this function can be used in a trigger and it will be translated into SQL

modelBuilder.Entity<Transaction>()
    .AfterDelete(trigger => trigger
        .Action(action => action
            .Condition(oldTransaction => oldTransaction.Description.Like('%payment%'))
            
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].