Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 27 additions & 49 deletions .github/workflows/publish-nuget.yml
Original file line number Diff line number Diff line change
@@ -1,62 +1,40 @@
name: Build and publish package
name: Build and Test

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
tags:
- '*.*.*'
branches: [ "**" ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@master

- name: Set release env
run: |
major_version=${GITHUB_REF:10:1} \
&& echo "MAJOR_VERSION=${major_version}" >> $GITHUB_ENV \
&& [[ $major_version = 5 ]] && echo "PROJECT_TARGET=netstandard2.1" >> $GITHUB_ENV || [[ $major_version = 6 ]] && echo "PROJECT_TARGET=net6.0" >> $GITHUB_ENV || [[ $major_version = 8 ]] && echo "PROJECT_TARGET=net8.0" || [[ $major_version = 9 ]] && echo "PROJECT_TARGET=net9.0" >> $GITHUB_ENV || echo "PROJECT_TARGET=net10.0" >> $GITHUB_ENV \
&& echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV

- name: Setup .NET5 environment
uses: actions/setup-dotnet@v5
with:
dotnet-version: '5.x.x'

- name: Setup .NET6 environment
uses: actions/setup-dotnet@v5
with:
dotnet-version: '6.x.x'

- name: Setup .NET8 environment
uses: actions/setup-dotnet@v5
with:
dotnet-version: '8.x.x'


- name: Setup .NET9 environment
uses: actions/setup-dotnet@v5
with:
dotnet-version: '9.x.x'

- name: Setup .NET10 environment
uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.x.x'

- name: Build project
run: |
for p in $(find ./src -name *.csproj); do dotnet build $p --framework ${{env.PROJECT_TARGET}} --configuration Release; done

- name: Generate a NuGet package
run: |
for p in $(find ./src -name *.csproj); do dotnet pack $p -p:TargetFrameworks=${{env.PROJECT_TARGET}} -p:PackageVersion=${{env.RELEASE_VERSION}} --no-build -c Release -o .; done

- name: Push to GitHub package registry
run: dotnet nuget push "*.nupkg" -k ${{secrets.NUGETORGTOKEN}} -s https://api.nuget.org/v3/index.json --skip-duplicate
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.x.x'

- name: Restore Dependencies
run: dotnet restore

- name: Build
run: dotnet build --no-restore

- name: Test
run: dotnet test --filter 'Category!=IntegrationTest' --no-build --verbosity normal

- name: Generate a NuGet package
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release/')
run: dotnet pack --no-build -o ./artifacts

- name: Push to GitHub package registry
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release/')
run: dotnet nuget push ./artifacts/*.nupkg -k ${{secrets.NUGETORGTOKEN}} -s https://api.nuget.org/v3/index.json --skip-duplicate
51 changes: 46 additions & 5 deletions Laraue.EfCoreTriggers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Laraue.EfCoreTriggers.SqlSe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laraue.EfCoreTriggers.TestMigration", "tests\Laraue.EfCoreTriggers.TestMigration\Laraue.EfCoreTriggers.TestMigration.csproj", "{50F9C440-4B10-4890-A266-A890341382EA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laraue.Linq2Triggers.Core", "src\Laraue.Linq2Triggers.Core\Laraue.Linq2Triggers.Core.csproj", "{955DBECF-08AD-4279-BEC1-FFFE8E6BD716}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laraue.Linq2Triggers.Providers.Sqlite", "src\Laraue.Linq2Triggers.Providers.Sqlite\Laraue.Linq2Triggers.Providers.Sqlite.csproj", "{A1C82905-D3CD-4AE3-A721-A87DD6CCAC7C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laraue.Linq2Triggers.Providers.MySql", "src\Laraue.Linq2Triggers.Providers.MySql\Laraue.Linq2Triggers.Providers.MySql.csproj", "{951A12A2-5F7D-4B70-922F-0C732E19674C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laraue.Linq2Triggers.Providers.PostgreSql", "src\Laraue.Linq2Triggers.Providers.PostgreSql\Laraue.Linq2Triggers.Providers.PostgreSql.csproj", "{E8456FDA-3423-4A10-9502-0E35D2016B22}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Laraue.Linq2Triggers.Providers.SqlServer", "src\Laraue.Linq2Triggers.Providers.SqlServer\Laraue.Linq2Triggers.Providers.SqlServer.csproj", "{79D843C8-6ADF-4ACB-A0D4-CCEAE251F8FE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{655AC9AF-B85B-43D3-B989-6FEA80417042}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ef", "ef", "{7E78BA60-159E-4E0C-973F-F00DA159D68C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -79,22 +93,49 @@ Global
{50F9C440-4B10-4890-A266-A890341382EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50F9C440-4B10-4890-A266-A890341382EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{50F9C440-4B10-4890-A266-A890341382EA}.Release|Any CPU.Build.0 = Release|Any CPU
{955DBECF-08AD-4279-BEC1-FFFE8E6BD716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{955DBECF-08AD-4279-BEC1-FFFE8E6BD716}.Debug|Any CPU.Build.0 = Debug|Any CPU
{955DBECF-08AD-4279-BEC1-FFFE8E6BD716}.Release|Any CPU.ActiveCfg = Release|Any CPU
{955DBECF-08AD-4279-BEC1-FFFE8E6BD716}.Release|Any CPU.Build.0 = Release|Any CPU
{A1C82905-D3CD-4AE3-A721-A87DD6CCAC7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1C82905-D3CD-4AE3-A721-A87DD6CCAC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1C82905-D3CD-4AE3-A721-A87DD6CCAC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1C82905-D3CD-4AE3-A721-A87DD6CCAC7C}.Release|Any CPU.Build.0 = Release|Any CPU
{951A12A2-5F7D-4B70-922F-0C732E19674C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{951A12A2-5F7D-4B70-922F-0C732E19674C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{951A12A2-5F7D-4B70-922F-0C732E19674C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{951A12A2-5F7D-4B70-922F-0C732E19674C}.Release|Any CPU.Build.0 = Release|Any CPU
{E8456FDA-3423-4A10-9502-0E35D2016B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8456FDA-3423-4A10-9502-0E35D2016B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8456FDA-3423-4A10-9502-0E35D2016B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8456FDA-3423-4A10-9502-0E35D2016B22}.Release|Any CPU.Build.0 = Release|Any CPU
{79D843C8-6ADF-4ACB-A0D4-CCEAE251F8FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79D843C8-6ADF-4ACB-A0D4-CCEAE251F8FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79D843C8-6ADF-4ACB-A0D4-CCEAE251F8FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79D843C8-6ADF-4ACB-A0D4-CCEAE251F8FE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{ECCF70FF-4296-4680-AD53-AA8352C4D663} = {9CDC27E2-01F4-4AA6-972C-D140415AA103}
{6D06F2CF-1D9D-43DA-AD0D-1EE0BE986481} = {7EE4BD3E-BA14-4823-A5E7-1464B3591407}
{156ECBF1-D1FF-48C5-94F8-362D05263C61} = {7EE4BD3E-BA14-4823-A5E7-1464B3591407}
{D1C6E7C5-3018-41AC-AD56-A054FF310B57} = {7EE4BD3E-BA14-4823-A5E7-1464B3591407}
{A2D4331D-EA4B-4F01-83EF-D2EE4A8097A7} = {7EE4BD3E-BA14-4823-A5E7-1464B3591407}
{F29864A8-ED88-4B3C-A340-15299FD90A56} = {7EE4BD3E-BA14-4823-A5E7-1464B3591407}
{95D6BB4B-77E8-42F2-B9FC-E6740DC89437} = {9CDC27E2-01F4-4AA6-972C-D140415AA103}
{EAF57617-5657-47D1-A719-424E1D6A63E8} = {9CDC27E2-01F4-4AA6-972C-D140415AA103}
{7B377F09-D92F-4844-AFC7-6642AC6174D1} = {9CDC27E2-01F4-4AA6-972C-D140415AA103}
{FBB5388A-4AFD-4891-A90A-51E59E364278} = {9CDC27E2-01F4-4AA6-972C-D140415AA103}
{50F9C440-4B10-4890-A266-A890341382EA} = {7EE4BD3E-BA14-4823-A5E7-1464B3591407}
{655AC9AF-B85B-43D3-B989-6FEA80417042} = {9CDC27E2-01F4-4AA6-972C-D140415AA103}
{955DBECF-08AD-4279-BEC1-FFFE8E6BD716} = {655AC9AF-B85B-43D3-B989-6FEA80417042}
{951A12A2-5F7D-4B70-922F-0C732E19674C} = {655AC9AF-B85B-43D3-B989-6FEA80417042}
{E8456FDA-3423-4A10-9502-0E35D2016B22} = {655AC9AF-B85B-43D3-B989-6FEA80417042}
{A1C82905-D3CD-4AE3-A721-A87DD6CCAC7C} = {655AC9AF-B85B-43D3-B989-6FEA80417042}
{79D843C8-6ADF-4ACB-A0D4-CCEAE251F8FE} = {655AC9AF-B85B-43D3-B989-6FEA80417042}
{7E78BA60-159E-4E0C-973F-F00DA159D68C} = {9CDC27E2-01F4-4AA6-972C-D140415AA103}
{ECCF70FF-4296-4680-AD53-AA8352C4D663} = {7E78BA60-159E-4E0C-973F-F00DA159D68C}
{7B377F09-D92F-4844-AFC7-6642AC6174D1} = {7E78BA60-159E-4E0C-973F-F00DA159D68C}
{95D6BB4B-77E8-42F2-B9FC-E6740DC89437} = {7E78BA60-159E-4E0C-973F-F00DA159D68C}
{EAF57617-5657-47D1-A719-424E1D6A63E8} = {7E78BA60-159E-4E0C-973F-F00DA159D68C}
{FBB5388A-4AFD-4891-A90A-51E59E364278} = {7E78BA60-159E-4E0C-973F-F00DA159D68C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3167DB00-67A4-49E7-A52F-CE3B5DBE02A6}
Expand Down
29 changes: 15 additions & 14 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# 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.
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](https://img.shields.io/nuget/v/Laraue.EfCoreTriggers.Common)](https://www.nuget.org/packages/Laraue.EfCoreTriggers.Common)
[![latest version](https://img.shields.io/nuget/dt/Laraue.EfCoreTriggers.Common)](https://www.nuget.org/packages/Laraue.EfCoreTriggers.Common)

#### Versions compatability
| Package version | .NET version | EF Core version |
| Package version | Min .NET version | EF Core version |
|-----------------|------------------|-----------------|
| 9.x.x | NET 9.0 | 9 |
| 10.x.x | NET 10.0 | 10 |
| 9.x.x | NET 8.0 | 9 |
| 8.x.x | NET 8.0 | 8 |
| 7.x.x | NET 6.0 | 7 |
| 5.x.x | NET standard 2.1 | 5 |
Expand Down Expand Up @@ -68,17 +69,17 @@ TriggerFunctions.GetColumnName<Transaction>(transaction => transaction.Value);

### 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 | + | + | + | - |
| 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

Expand Down
27 changes: 27 additions & 0 deletions src/Laraue.EfCoreTriggers.Common/EfCoreTriggerEntityType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using Laraue.Linq2Triggers.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace Laraue.EfCoreTriggers.Common;

/// <inheritdoc />
public class EfCoreTriggerEntityType : ITriggerEntityType
{
private readonly IEntityType _entityType;

/// <summary>
/// Initializes a EF core wrapper for <see cref="ITriggerEntityType"/>.
/// </summary>
/// <param name="entityType"></param>
public EfCoreTriggerEntityType(IEntityType entityType)
{
_entityType = entityType;
}

/// <inheritdoc />
public Type ClrType => _entityType.ClrType;

/// <inheritdoc />
public string? GetSchema() => _entityType.GetSchema();
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ public EfCoreTriggersExtensionInfo(IDbContextOptionsExtension extension)
}

/// <inheritdoc />
#if NET6_0_OR_GREATER
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
{
return string.Equals(LogFragment, other.LogFragment, StringComparison.Ordinal);
}
public override int GetServiceProviderHashCode() => 0;
#else
public override long GetServiceProviderHashCode() => 0;
#endif
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
{
return string.Equals(LogFragment, other.LogFragment, StringComparison.Ordinal);
}

/// <inheritdoc />
public override int GetServiceProviderHashCode() => 0;

/// <inheritdoc />
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.Linq;
using System.Reflection;
using Laraue.EfCoreTriggers.Common.TriggerBuilders;
using Laraue.EfCoreTriggers.Common.TriggerBuilders.Abstractions;
using Laraue.EfCoreTriggers.Common.TriggerBuilders.TableRefs;
using Laraue.EfCoreTriggers.Common.Migrations;
using Laraue.EfCoreTriggers.Common.SqlGeneration;
using Laraue.Linq2Triggers.Core.TriggerBuilders;
using Laraue.Linq2Triggers.Core.TriggerBuilders.Abstractions;
using Laraue.Linq2Triggers.Core.TriggerBuilders.TableRefs;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

Expand All @@ -30,9 +32,7 @@ private static EntityTypeBuilder<T> AddTriggerAnnotation<T>(
var entityType = entityTypeBuilder.Metadata.Model.FindEntityType(entityTypeName)
?? throw new InvalidOperationException($"Entity {entityTypeName} metadata was not found");

#if NET6_0_OR_GREATER
entityTypeBuilder.ToTable(tb => tb.HasTrigger(configuredTrigger.Name));
#endif
entityType.AddAnnotation(configuredTrigger.Name, configuredTrigger);

return entityTypeBuilder;
Expand Down Expand Up @@ -243,9 +243,9 @@ public static void AddGenericTrigger<TBaseTriggerEntity>(
Func<Type[], Type[]>? inheritorsFilter = null)
where TBaseTriggerEntity : class
{
var inheritors = Assembly.GetAssembly(typeof(TBaseTriggerEntity))
var inheritors = Assembly.GetAssembly(typeof(TBaseTriggerEntity))!
.GetTypes()
.Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(TBaseTriggerEntity)))
.Where(myType => myType is { IsClass: true, IsAbstract: false } && myType.IsSubclassOf(typeof(TBaseTriggerEntity)))
.ToArray();

if (inheritorsFilter is not null)
Expand Down
Loading