Skip to content

Commit 6c745da

Browse files
committed
Proper extension methods for ease of use
1 parent 901ee94 commit 6c745da

2 files changed

Lines changed: 155 additions & 4 deletions

File tree

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,65 @@
11
using System;
2+
using System.Threading.Tasks;
3+
using System.Threading;
24
using Microsoft.EntityFrameworkCore;
35
using Microsoft.EntityFrameworkCore.Infrastructure;
46

57
namespace EntityFrameworkCore.Triggered.Extensions
68
{
79
public static class DbContextExtensions
810
{
11+
public static ITriggerService GetTriggerService(this DbContext dbContext)
12+
{
13+
if (dbContext is null)
14+
{
15+
throw new ArgumentNullException(nameof(dbContext));
16+
}
17+
18+
return dbContext.GetService<ITriggerService>() ?? throw new InvalidOperationException("Triggers are not configured for this DbContext");
19+
}
20+
921
public static ITriggerSession CreateTriggerSession(this DbContext dbContext, IServiceProvider? serviceProvider = null)
1022
{
11-
var triggerService = dbContext.GetService<ITriggerService>() ?? throw new InvalidOperationException("Trigger service infrastructure is not configured");
23+
var triggerService = GetTriggerService(dbContext);
1224

1325
return triggerService.CreateSession(dbContext, serviceProvider);
1426
}
27+
28+
public static int SaveChangesWithoutTriggers(this DbContext dbContext, bool acceptAllChangesOnSuccess = true)
29+
{
30+
var triggerService = GetTriggerService(dbContext);
31+
var initialConfiguration = triggerService.Configuration;
32+
33+
try
34+
{
35+
triggerService.Configuration = initialConfiguration with { Disabled = true };
36+
37+
return dbContext.SaveChanges(acceptAllChangesOnSuccess);
38+
}
39+
finally
40+
{
41+
triggerService.Configuration = initialConfiguration;
42+
}
43+
}
44+
45+
public static Task<int> SaveChangesWithoutTriggersAsync(this DbContext dbContext, CancellationToken cancellationToken = default)
46+
=> SaveChangesWithoutTriggersAsync(dbContext, true, cancellationToken);
47+
48+
public static Task<int> SaveChangesWithoutTriggersAsync(this DbContext dbContext, bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
49+
{
50+
var triggerService = GetTriggerService(dbContext);
51+
var initialConfiguration = triggerService.Configuration;
52+
53+
try
54+
{
55+
triggerService.Configuration = initialConfiguration with { Disabled = true };
56+
57+
return dbContext.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
58+
}
59+
finally
60+
{
61+
triggerService.Configuration = initialConfiguration;
62+
}
63+
}
1564
}
1665
}

test/EntityFrameworkCore.Triggered.Tests/Extensions/DbContextExtensionTests.cs

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using EntityFrameworkCore.Triggered.Extensions;
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using EntityFrameworkCore.Triggered.Extensions;
25
using Microsoft.EntityFrameworkCore;
36
using Microsoft.EntityFrameworkCore.Diagnostics;
47
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -10,28 +13,127 @@ public class DbContextExtensionTests
1013
{
1114
class TestModel { public int Id { get; set; } public string Name { get; set; } }
1215

16+
class SampleTrigger : IBeforeSaveTrigger<TestModel>
17+
{
18+
public int BeforeSaveCalls { get; set; }
19+
20+
public Task BeforeSave(ITriggerContext<TestModel> context, CancellationToken cancellationToken)
21+
{
22+
BeforeSaveCalls += 1;
23+
return Task.CompletedTask;
24+
}
25+
}
26+
1327
class TestDbContext : DbContext
1428
{
29+
public bool UseTriggers { get; set; } = true;
30+
1531
public DbSet<TestModel> TestModels { get; set; }
1632

33+
public SampleTrigger SampleTrigger { get; } = new();
34+
1735
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
1836
{
19-
optionsBuilder.UseInMemoryDatabase("test").UseTriggers();
37+
optionsBuilder.UseInMemoryDatabase("test");
38+
if (UseTriggers)
39+
{
40+
optionsBuilder.UseTriggers(triggerOptions => {
41+
triggerOptions.AddTrigger(SampleTrigger);
42+
});
43+
}
2044

2145
optionsBuilder.ConfigureWarnings(warningOptions => {
2246
warningOptions.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning);
2347
});
2448
}
2549
}
2650

51+
[Fact]
52+
public void GetTriggerService_ValidDbContext_ReturnsSession()
53+
{
54+
using var context = new TestDbContext();
55+
56+
var triggerService = DbContextExtensions.GetTriggerService(context);
57+
58+
Assert.NotNull(triggerService);
59+
}
60+
61+
62+
[Fact]
63+
public void GetTriggerService_NonTriggeredDbContext_ReturnsSession()
64+
{
65+
using var context = new TestDbContext { UseTriggers = false };
66+
67+
Assert.Throws<InvalidOperationException>(() =>
68+
DbContextExtensions.GetTriggerService(context));
69+
}
70+
2771
[Fact]
2872
public void CreateTriggerSession_ValidDbContext_CreatesNewSession()
2973
{
30-
var context = new TestDbContext();
74+
using var context = new TestDbContext();
3175
var triggerSession = DbContextExtensions.CreateTriggerSession(context);
3276

3377
Assert.NotNull(triggerSession);
3478
Assert.NotNull(context.GetService<ITriggerService>()?.Current);
3579
}
80+
81+
[Fact]
82+
public void SaveChangesWithoutTriggers_DoesNotRaiseTrigger()
83+
{
84+
// arrange
85+
using var context = new TestDbContext();
86+
context.TestModels.Add(new TestModel { });
87+
88+
// act
89+
context.SaveChangesWithoutTriggers();
90+
91+
// assert
92+
Assert.Equal(0, context.SampleTrigger.BeforeSaveCalls);
93+
}
94+
95+
[Fact]
96+
public void SaveChangesWithoutTriggers_RestoresConfiguration()
97+
{
98+
// arrange
99+
using var context = new TestDbContext();
100+
context.TestModels.Add(new TestModel { });
101+
var expectedConfiguration = context.GetTriggerService().Configuration;
102+
103+
// act
104+
context.SaveChangesWithoutTriggers();
105+
106+
// assert
107+
Assert.Same(expectedConfiguration, context.GetTriggerService().Configuration);
108+
}
109+
110+
[Fact]
111+
public async Task SaveChangesAsyncWithoutTriggers_DoesNotRaiseTrigger()
112+
{
113+
// arrange
114+
using var context = new TestDbContext();
115+
context.TestModels.Add(new TestModel { });
116+
117+
// act
118+
await context.SaveChangesWithoutTriggersAsync();
119+
120+
// assert
121+
Assert.Equal(0, context.SampleTrigger.BeforeSaveCalls);
122+
}
123+
124+
[Fact]
125+
public async Task SaveChangesAsyncWithoutTriggers_RestoresConfiguration()
126+
{
127+
// arrange
128+
using var context = new TestDbContext();
129+
context.TestModels.Add(new TestModel { });
130+
var expectedConfiguration = context.GetTriggerService().Configuration;
131+
132+
// act
133+
await context.SaveChangesWithoutTriggersAsync();
134+
135+
// assert
136+
Assert.Same(expectedConfiguration, context.GetTriggerService().Configuration);
137+
}
36138
}
37139
}

0 commit comments

Comments
 (0)