diff --git a/Directory.build.props b/Directory.build.props
index c524074..8f5af2b 100644
--- a/Directory.build.props
+++ b/Directory.build.props
@@ -5,11 +5,11 @@
Dominic Jonas
DoJo.EntityFrameworkCore.DbContextScope
https://github.com/dojo90/DbContextScope
- https://raw.githubusercontent.com/dojo90/DbContextScope/master/LICENSE
+ https://raw.githubusercontent.com/dojo90/DbContextScope/master/LICENSE
git@github.com:dojo90/DbContextScope.git
git
sentinel nlog
- DbContextScope for EF Core. Forked from https://github.com/tncalvert/DbContextScope.
+ DbContextScope for EF v2|v3 Core. Forked from https://github.com/tncalvert/DbContextScope.
EntityFramework EFCore DbContext DbContextScope
diff --git a/README.md b/README.md
index e86e337..6cde05b 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,15 @@
## Foreword
-This is a fork from [tncalvert/DbContextScope](https://github.com/tncalvert/DbContextScope). The biggest innovation is the `multitarget support`.
+This is a fork from [tncalvert/DbContextScope](https://github.com/tncalvert/DbContextScope). The target framework is `.NET Standart2.0` and minimum `Microsoft.EntityFrameworkCore` version is `v2.0.0`.
-- `.NET Framework v4.6.1` -> **Microsoft.EntityFrameworkCore v2.x**
-- `.NET CoreApp v2.0` -> **Microsoft.EntityFrameworkCore v2.x**
-- `.NET CoreApp v3.0` -> **Microsoft.EntityFrameworkCore v3.x**
+If you use this library in your project, please note to use same `nuget versions`! The `DbContextScope` uses `Microsoft.EntityFrameworkCore.Relational v2.0.0`!
+
+Example `*.csproj` to use `v3.1.1`:
+
+```xml
+
+
+```
## Nuget
diff --git a/src/DbContextScope.DemoConsoleApp/DbContextScope.DemoConsoleApp.csproj b/src/DbContextScope.DemoConsoleApp/DbContextScope.DemoConsoleApp.csproj
deleted file mode 100644
index cb582af..0000000
--- a/src/DbContextScope.DemoConsoleApp/DbContextScope.DemoConsoleApp.csproj
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
- Exe
- net461;netcoreapp2.0;netcoreapp3.0
- DoJo.EntityFrameworkCore.DemoConsoleApp
-
-
- NET461;NETFULL
-
-
- NETCORE;NETSTANDARD;NETCOREAPP2_0
-
-
- NETCORE;NETSTANDARD;NETCOREAPP3_0
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/DbContextScope.DemoConsoleApp/Program.cs b/src/DbContextScope.DemoConsoleApp/Program.cs
deleted file mode 100644
index 4d41971..0000000
--- a/src/DbContextScope.DemoConsoleApp/Program.cs
+++ /dev/null
@@ -1,169 +0,0 @@
-using System;
-using System.Linq;
-using DbContextScope.DemoConsoleApp.BusinessLogicServices;
-using DbContextScope.DemoConsoleApp.CommandModel;
-using DbContextScope.DemoConsoleApp.DatabaseContext;
-using DbContextScope.DemoConsoleApp.Repositories;
-using EntityFrameworkCore.DbContextScope;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Diagnostics;
-
-namespace DbContextScope.DemoConsoleApp
-{
- class Program
- {
- static void Main(string[] args)
- {
- //-- Poor-man DI - build our dependencies by hand for this demo
- var dbContextScopeFactory = new DbContextScopeFactory(new DbContextFactory());
- var ambientDbContextLocator = new AmbientDbContextLocator();
- var userRepository = new UserRepository(ambientDbContextLocator);
-
- var userCreationService = new UserCreationService(dbContextScopeFactory, userRepository);
- var userQueryService = new UserQueryService(dbContextScopeFactory, userRepository);
- var userEmailService = new UserEmailService(dbContextScopeFactory);
- var userCreditScoreService = new UserCreditScoreService(dbContextScopeFactory);
-
- try
- {
- Console.WriteLine(
- "This demo uses an EF Core In Memory database. It does not create any external databases.");
- Console.WriteLine("");
-
- //-- Demo of typical usage for read and writes
- Console.WriteLine("Creating a user called Mary...");
- var marysSpec = new UserCreationSpec("Mary", "mary@example.com");
- userCreationService.CreateUser(marysSpec);
- Console.WriteLine("Done.\n");
-
- Console.WriteLine("Trying to retrieve our newly created user from the data store...");
- var mary = userQueryService.GetUser(marysSpec.Id);
- Console.WriteLine("OK. Persisted user: {0}", mary);
-
- Console.WriteLine("Press enter to continue...");
- Console.ReadLine();
-
- //-- Demo of nested DbContextScopes
- Console.WriteLine("Creating 2 new users called John and Jeanne in an atomic transaction...");
- var johnSpec = new UserCreationSpec("John", "john@example.com");
- var jeanneSpec = new UserCreationSpec("Jeanne", "jeanne@example.com");
- userCreationService.CreateListOfUsers(johnSpec, jeanneSpec);
- Console.WriteLine("Done.\n");
-
- Console.WriteLine("Trying to retrieve our newly created users from the data store...");
- var createdUsers = userQueryService.GetUsers(johnSpec.Id, jeanneSpec.Id);
- Console.WriteLine("OK. Found {0} persisted users.", createdUsers.Count());
-
- Console.WriteLine("Press enter to continue...");
- Console.ReadLine();
-
- //-- Demo of nested DbContextScopes in the face of an exception.
- // If any of the provided users failed to get persisted, none should get persisted.
- Console.WriteLine(
- "Creating 2 new users called Julie and Marc in an atomic transaction. Will make the persistence of the second user fail intentionally in order to test the atomicity of the transaction...");
- var julieSpec = new UserCreationSpec("Julie", "julie@example.com");
- var marcSpec = new UserCreationSpec("Marc", "marc@example.com");
- try
- {
- userCreationService.CreateListOfUsersWithIntentionalFailure(julieSpec, marcSpec);
- Console.WriteLine("Done.\n");
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- Console.WriteLine();
- }
-
- Console.WriteLine("Trying to retrieve our newly created users from the data store...");
- var maybeCreatedUsers = userQueryService.GetUsers(julieSpec.Id, marcSpec.Id);
- Console.WriteLine(
- "Found {0} persisted users. If this number is 0, we're all good. If this number is not 0, we have a big problem.",
- maybeCreatedUsers.Count());
-
- Console.WriteLine("Press enter to continue...");
- Console.ReadLine();
-
- //-- Demo of DbContextScope within an async flow
- Console.WriteLine(
- "Trying to retrieve two users John and Jeanne sequentially in an asynchronous manner...");
- // We're going to block on the async task here as we don't have a choice. No risk of deadlocking in any case as console apps
- // don't have a synchronization context.
- var usersFoundAsync = userQueryService.GetTwoUsersAsync(johnSpec.Id, jeanneSpec.Id).Result;
- Console.WriteLine("OK. Found {0} persisted users.", usersFoundAsync.Count());
-
- Console.WriteLine("Press enter to continue...");
- Console.ReadLine();
-
- //-- Demo of explicit database transaction.
- Console.WriteLine("Trying to retrieve user John within a READ UNCOMMITTED database transaction...");
- // You'll want to use SQL Profiler or Entity Framework Profiler to verify that the correct transaction isolation
- // level is being used.
- var userMaybeUncommitted = userQueryService.GetUserUncommitted(johnSpec.Id);
- Console.WriteLine("OK. User found: {0}", userMaybeUncommitted);
-
- Console.WriteLine("Press enter to continue...");
- Console.ReadLine();
-
- //-- Demo of disabling the DbContextScope nesting behaviour in order to force the persistence of changes made to entities
- // This is a pretty advanced feature that you can safely ignore until you actually need it.
- Console.WriteLine("Will simulate sending a Welcome email to John...");
-
- using (var parentScope = dbContextScopeFactory.Create())
- {
- var parentDbContext = parentScope.DbContexts.Get();
-
- // Load John in the parent DbContext
- var john = parentDbContext.Users.Find(johnSpec.Id);
- Console.WriteLine("Before calling SendWelcomeEmail(), john.WelcomeEmailSent = " +
- john.WelcomeEmailSent);
-
- // Now call our SendWelcomeEmail() business logic service method, which will
- // update John in a non-nested child context
- userEmailService.SendWelcomeEmail(johnSpec.Id);
-
- // Verify that we can see the modifications made to John by the SendWelcomeEmail() method
- Console.WriteLine("After calling SendWelcomeEmail(), john.WelcomeEmailSent = " +
- john.WelcomeEmailSent);
-
- // Note that even though we're not calling SaveChanges() in the parent scope here, the changes
- // made to John by SendWelcomeEmail() will remain persisted in the database as SendWelcomeEmail()
- // forced the creation of a new DbContextScope.
- }
-
- Console.WriteLine("Press enter to continue...");
- Console.ReadLine();
-
- //-- Demonstration of DbContextScope and parallel programming
- Console.WriteLine(
- "Calculating and storing the credit score of all users in the database in parallel...");
- userCreditScoreService.UpdateCreditScoreForAllUsers();
- Console.WriteLine("Done.");
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- }
-
- Console.WriteLine();
- Console.WriteLine("The end.");
- Console.WriteLine("Press enter to exit...");
- Console.ReadLine();
- }
- }
-
- class DbContextFactory : IDbContextFactory
- {
- public TDbContext CreateDbContext() where TDbContext : DbContext
- {
- if (typeof(TDbContext) == typeof(UserManagementDbContext))
- {
- var config = new DbContextOptionsBuilder()
- .UseInMemoryDatabase("1337")
- .ConfigureWarnings(warnings => { warnings.Ignore(InMemoryEventId.TransactionIgnoredWarning); });
- return new UserManagementDbContext(config.Options) as TDbContext;
- }
-
- throw new NotImplementedException(typeof(TDbContext).Name);
- }
- }
-}
\ No newline at end of file
diff --git a/src/DbContextScope.Test/BusinessLogicServices/UserCreationService.cs b/src/DbContextScope.EF2.Test/BusinessLogicServices/UserCreationService.cs
similarity index 100%
rename from src/DbContextScope.Test/BusinessLogicServices/UserCreationService.cs
rename to src/DbContextScope.EF2.Test/BusinessLogicServices/UserCreationService.cs
diff --git a/src/DbContextScope.Test/BusinessLogicServices/UserCreditScoreService.cs b/src/DbContextScope.EF2.Test/BusinessLogicServices/UserCreditScoreService.cs
similarity index 100%
rename from src/DbContextScope.Test/BusinessLogicServices/UserCreditScoreService.cs
rename to src/DbContextScope.EF2.Test/BusinessLogicServices/UserCreditScoreService.cs
diff --git a/src/DbContextScope.Test/BusinessLogicServices/UserEmailService.cs b/src/DbContextScope.EF2.Test/BusinessLogicServices/UserEmailService.cs
similarity index 100%
rename from src/DbContextScope.Test/BusinessLogicServices/UserEmailService.cs
rename to src/DbContextScope.EF2.Test/BusinessLogicServices/UserEmailService.cs
diff --git a/src/DbContextScope.Test/BusinessLogicServices/UserQueryService.cs b/src/DbContextScope.EF2.Test/BusinessLogicServices/UserQueryService.cs
similarity index 100%
rename from src/DbContextScope.Test/BusinessLogicServices/UserQueryService.cs
rename to src/DbContextScope.EF2.Test/BusinessLogicServices/UserQueryService.cs
diff --git a/src/DbContextScope.Test/CommandModel/UserCreationSpec.cs b/src/DbContextScope.EF2.Test/CommandModel/UserCreationSpec.cs
similarity index 100%
rename from src/DbContextScope.Test/CommandModel/UserCreationSpec.cs
rename to src/DbContextScope.EF2.Test/CommandModel/UserCreationSpec.cs
diff --git a/src/DbContextScope.Test/DatabaseContext/UserManagementDbContext.cs b/src/DbContextScope.EF2.Test/DatabaseContext/UserManagementDbContext.cs
similarity index 100%
rename from src/DbContextScope.Test/DatabaseContext/UserManagementDbContext.cs
rename to src/DbContextScope.EF2.Test/DatabaseContext/UserManagementDbContext.cs
diff --git a/src/DbContextScope.EF2.Test/DbContextScope.EF2.Test.csproj b/src/DbContextScope.EF2.Test/DbContextScope.EF2.Test.csproj
new file mode 100644
index 0000000..b19401b
--- /dev/null
+++ b/src/DbContextScope.EF2.Test/DbContextScope.EF2.Test.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net461;netcoreapp2.0;netcoreapp3.0
+ false
+ EntityFrameworkCore.DbContextScope.Test
+ DoJo.EntityFrameworkCore.DbContextScope.Test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DbContextScope.Test/DbContextScopeTest.cs b/src/DbContextScope.EF2.Test/DbContextScopeTest.cs
similarity index 100%
rename from src/DbContextScope.Test/DbContextScopeTest.cs
rename to src/DbContextScope.EF2.Test/DbContextScopeTest.cs
diff --git a/src/DbContextScope.Test/DomainModel/User.cs b/src/DbContextScope.EF2.Test/DomainModel/User.cs
similarity index 100%
rename from src/DbContextScope.Test/DomainModel/User.cs
rename to src/DbContextScope.EF2.Test/DomainModel/User.cs
diff --git a/src/DbContextScope.Test/Repositories/IUserRepository.cs b/src/DbContextScope.EF2.Test/Repositories/IUserRepository.cs
similarity index 100%
rename from src/DbContextScope.Test/Repositories/IUserRepository.cs
rename to src/DbContextScope.EF2.Test/Repositories/IUserRepository.cs
diff --git a/src/DbContextScope.DemoConsoleApp/Repositories/UserRepository.cs b/src/DbContextScope.EF2.Test/Repositories/UserRepository.cs
similarity index 87%
rename from src/DbContextScope.DemoConsoleApp/Repositories/UserRepository.cs
rename to src/DbContextScope.EF2.Test/Repositories/UserRepository.cs
index 3bf9946..e93b165 100644
--- a/src/DbContextScope.DemoConsoleApp/Repositories/UserRepository.cs
+++ b/src/DbContextScope.EF2.Test/Repositories/UserRepository.cs
@@ -1,10 +1,9 @@
using System;
using System.Threading.Tasks;
-using DbContextScope.DemoConsoleApp.DatabaseContext;
-using DbContextScope.DemoConsoleApp.DomainModel;
-using EntityFrameworkCore.DbContextScope;
+using EntityFrameworkCore.DbContextScope.Test.DatabaseContext;
+using EntityFrameworkCore.DbContextScope.Test.DomainModel;
-namespace DbContextScope.DemoConsoleApp.Repositories {
+namespace EntityFrameworkCore.DbContextScope.Test.Repositories {
/*
* An example "repository" relying on an ambient DbContext instance.
*
@@ -45,12 +44,14 @@ public User Get(Guid userId) {
public Task GetAsync(Guid userId)
{
-#if NETCOREAPP2_0 || NET461
return DbContext.Users.FindAsync(userId);
-#endif
-#if NETCOREAPP3_0
- return DbContext.Users.FindAsync(userId).AsTask();
-#endif
+
+//#if NETCOREAPP2_0 || NET461
+// return DbContext.Users.FindAsync(userId);
+//#endif
+//#if NETCOREAPP3_0
+// return DbContext.Users.FindAsync(userId).AsTask();
+//#endif
}
public void Add(User user) {
diff --git a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserCreationService.cs b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserCreationService.cs
similarity index 94%
rename from src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserCreationService.cs
rename to src/DbContextScope.EF3.Test/BusinessLogicServices/UserCreationService.cs
index 9c09c87..ece6d66 100644
--- a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserCreationService.cs
+++ b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserCreationService.cs
@@ -1,10 +1,9 @@
using System;
-using DbContextScope.DemoConsoleApp.CommandModel;
-using DbContextScope.DemoConsoleApp.DomainModel;
-using DbContextScope.DemoConsoleApp.Repositories;
-using EntityFrameworkCore.DbContextScope;
+using EntityFrameworkCore.DbContextScope.Test.CommandModel;
+using EntityFrameworkCore.DbContextScope.Test.DomainModel;
+using EntityFrameworkCore.DbContextScope.Test.Repositories;
-namespace DbContextScope.DemoConsoleApp.BusinessLogicServices {
+namespace EntityFrameworkCore.DbContextScope.Test.BusinessLogicServices {
/*
* Example business logic service implementing command functionalities (i.e. create / update actions).
*/
diff --git a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserCreditScoreService.cs b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserCreditScoreService.cs
similarity index 94%
rename from src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserCreditScoreService.cs
rename to src/DbContextScope.EF3.Test/BusinessLogicServices/UserCreditScoreService.cs
index 0b1b06d..85be0fc 100644
--- a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserCreditScoreService.cs
+++ b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserCreditScoreService.cs
@@ -2,10 +2,9 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using DbContextScope.DemoConsoleApp.DatabaseContext;
-using EntityFrameworkCore.DbContextScope;
+using EntityFrameworkCore.DbContextScope.Test.DatabaseContext;
-namespace DbContextScope.DemoConsoleApp.BusinessLogicServices {
+namespace EntityFrameworkCore.DbContextScope.Test.BusinessLogicServices {
public class UserCreditScoreService {
private readonly IDbContextScopeFactory _dbContextScopeFactory;
diff --git a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserEmailService.cs b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserEmailService.cs
similarity index 93%
rename from src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserEmailService.cs
rename to src/DbContextScope.EF3.Test/BusinessLogicServices/UserEmailService.cs
index e818489..44b90d3 100644
--- a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserEmailService.cs
+++ b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserEmailService.cs
@@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
-using DbContextScope.DemoConsoleApp.DatabaseContext;
-using DbContextScope.DemoConsoleApp.DomainModel;
-using EntityFrameworkCore.DbContextScope;
+using EntityFrameworkCore.DbContextScope.Test.DatabaseContext;
+using EntityFrameworkCore.DbContextScope.Test.DomainModel;
-namespace DbContextScope.DemoConsoleApp.BusinessLogicServices {
+namespace EntityFrameworkCore.DbContextScope.Test.BusinessLogicServices {
public class UserEmailService {
private readonly IDbContextScopeFactory _dbContextScopeFactory;
diff --git a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserQueryService.cs b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserQueryService.cs
similarity index 95%
rename from src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserQueryService.cs
rename to src/DbContextScope.EF3.Test/BusinessLogicServices/UserQueryService.cs
index f29fa52..5857a80 100644
--- a/src/DbContextScope.DemoConsoleApp/BusinessLogicServices/UserQueryService.cs
+++ b/src/DbContextScope.EF3.Test/BusinessLogicServices/UserQueryService.cs
@@ -3,12 +3,11 @@
using System.Data;
using System.Linq;
using System.Threading.Tasks;
-using DbContextScope.DemoConsoleApp.DatabaseContext;
-using DbContextScope.DemoConsoleApp.DomainModel;
-using DbContextScope.DemoConsoleApp.Repositories;
-using EntityFrameworkCore.DbContextScope;
+using EntityFrameworkCore.DbContextScope.Test.DatabaseContext;
+using EntityFrameworkCore.DbContextScope.Test.DomainModel;
+using EntityFrameworkCore.DbContextScope.Test.Repositories;
-namespace DbContextScope.DemoConsoleApp.BusinessLogicServices {
+namespace EntityFrameworkCore.DbContextScope.Test.BusinessLogicServices {
/*
* Example business logic service implementing query functionalities (i.e. read actions).
*/
diff --git a/src/DbContextScope.DemoConsoleApp/CommandModel/UserCreationSpec.cs b/src/DbContextScope.EF3.Test/CommandModel/UserCreationSpec.cs
similarity index 91%
rename from src/DbContextScope.DemoConsoleApp/CommandModel/UserCreationSpec.cs
rename to src/DbContextScope.EF3.Test/CommandModel/UserCreationSpec.cs
index 30bd483..05cfc47 100644
--- a/src/DbContextScope.DemoConsoleApp/CommandModel/UserCreationSpec.cs
+++ b/src/DbContextScope.EF3.Test/CommandModel/UserCreationSpec.cs
@@ -1,6 +1,6 @@
using System;
-namespace DbContextScope.DemoConsoleApp.CommandModel {
+namespace EntityFrameworkCore.DbContextScope.Test.CommandModel {
///
/// Specifications of the CreateUser command. Defines the properties of a new user.
///
diff --git a/src/DbContextScope.DemoConsoleApp/DatabaseContext/UserManagementDbContext.cs b/src/DbContextScope.EF3.Test/DatabaseContext/UserManagementDbContext.cs
similarity index 83%
rename from src/DbContextScope.DemoConsoleApp/DatabaseContext/UserManagementDbContext.cs
rename to src/DbContextScope.EF3.Test/DatabaseContext/UserManagementDbContext.cs
index 259786a..fe4112d 100644
--- a/src/DbContextScope.DemoConsoleApp/DatabaseContext/UserManagementDbContext.cs
+++ b/src/DbContextScope.EF3.Test/DatabaseContext/UserManagementDbContext.cs
@@ -1,7 +1,7 @@
-using DbContextScope.DemoConsoleApp.DomainModel;
+using EntityFrameworkCore.DbContextScope.Test.DomainModel;
using Microsoft.EntityFrameworkCore;
-namespace DbContextScope.DemoConsoleApp.DatabaseContext {
+namespace EntityFrameworkCore.DbContextScope.Test.DatabaseContext {
public class UserManagementDbContext : DbContext {
// Map our 'User' model by convention
public DbSet Users { get; set; }
diff --git a/src/DbContextScope.EF3.Test/DbContextScope.EF3.Test.csproj b/src/DbContextScope.EF3.Test/DbContextScope.EF3.Test.csproj
new file mode 100644
index 0000000..24cf54c
--- /dev/null
+++ b/src/DbContextScope.EF3.Test/DbContextScope.EF3.Test.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net461;netcoreapp2.0;netcoreapp3.0
+ false
+ EntityFrameworkCore.DbContextScope.Test
+ DoJo.EntityFrameworkCore.DbContextScope.Test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DbContextScope.EF3.Test/DbContextScopeTest.cs b/src/DbContextScope.EF3.Test/DbContextScopeTest.cs
new file mode 100644
index 0000000..2e70509
--- /dev/null
+++ b/src/DbContextScope.EF3.Test/DbContextScopeTest.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Linq;
+using EntityFrameworkCore.DbContextScope.Test.BusinessLogicServices;
+using EntityFrameworkCore.DbContextScope.Test.CommandModel;
+using EntityFrameworkCore.DbContextScope.Test.DatabaseContext;
+using EntityFrameworkCore.DbContextScope.Test.DomainModel;
+using EntityFrameworkCore.DbContextScope.Test.Repositories;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace EntityFrameworkCore.DbContextScope.Test
+{
+ public static class UserSpecExtensions
+ {
+ public static void Equal(this UserCreationSpec spec, User user)
+ {
+ Assert.NotNull(spec);
+ Assert.NotNull(user);
+ Assert.Equal(spec.Id, user.Id);
+ Assert.Equal(spec.Email, user.Email);
+ Assert.Equal(spec.Name, user.Name);
+ }
+ }
+
+ public class DbContextScopeTest
+ {
+ private readonly ITestOutputHelper _Output;
+
+ public DbContextScopeTest(ITestOutputHelper output)
+ {
+ _Output = output;
+ }
+
+ private class DbContextFactory : IDbContextFactory
+ {
+ public TDbContext CreateDbContext() where TDbContext : DbContext
+ {
+ if (typeof(TDbContext) == typeof(UserManagementDbContext))
+ {
+ var config = new DbContextOptionsBuilder()
+ .UseInMemoryDatabase("1337")
+ .ConfigureWarnings(warnings => { warnings.Ignore(InMemoryEventId.TransactionIgnoredWarning); });
+ return new UserManagementDbContext(config.Options) as TDbContext;
+ }
+
+ throw new NotImplementedException(typeof(TDbContext).Name);
+ }
+ }
+
+ [Fact]
+ public void FullTest()
+ {
+ //-- Poor-man DI - build our dependencies by hand for this demo
+ var dbContextScopeFactory = new DbContextScopeFactory(new DbContextFactory());
+ var ambientDbContextLocator = new AmbientDbContextLocator();
+ var userRepository = new UserRepository(ambientDbContextLocator);
+
+ var userCreationService = new UserCreationService(dbContextScopeFactory, userRepository);
+ var userQueryService = new UserQueryService(dbContextScopeFactory, userRepository);
+ var userEmailService = new UserEmailService(dbContextScopeFactory);
+ var userCreditScoreService = new UserCreditScoreService(dbContextScopeFactory);
+
+ _Output.WriteLine(
+ "This demo uses an EF Core In Memory database. It does not create any external databases.");
+ _Output.WriteLine("");
+
+ //-- Demo of typical usage for read and writes
+ _Output.WriteLine("Creating a user called Mary...");
+ var marysSpec = new UserCreationSpec("Mary", "mary@example.com");
+ userCreationService.CreateUser(marysSpec);
+ _Output.WriteLine("Done.\n");
+
+ _Output.WriteLine("Trying to retrieve our newly created user from the data store...");
+ var mary = userQueryService.GetUser(marysSpec.Id);
+ _Output.WriteLine("OK. Persisted user: {0}", mary);
+ marysSpec.Equal(mary);
+
+ //-- Demo of nested DbContextScopes
+ _Output.WriteLine("Creating 2 new users called John and Jeanne in an atomic transaction...");
+ var johnSpec = new UserCreationSpec("John", "john@example.com");
+ var jeanneSpec = new UserCreationSpec("Jeanne", "jeanne@example.com");
+ userCreationService.CreateListOfUsers(johnSpec, jeanneSpec);
+ _Output.WriteLine("Done.\n");
+
+ _Output.WriteLine("Trying to retrieve our newly created users from the data store...");
+ var createdUsers = userQueryService.GetUsers(johnSpec.Id, jeanneSpec.Id).ToList();
+ _Output.WriteLine("OK. Found {0} persisted users.", createdUsers.Count);
+
+ Assert.Equal(2, createdUsers.Count);
+ johnSpec.Equal(createdUsers[0]);
+ jeanneSpec.Equal(createdUsers[1]);
+
+ //-- Demo of nested DbContextScopes in the face of an exception.
+ // If any of the provided users failed to get persisted, none should get persisted.
+ _Output.WriteLine(
+ "Creating 2 new users called Julie and Marc in an atomic transaction. Will make the persistence of the second user fail intentionally in order to test the atomicity of the transaction...");
+ var julieSpec = new UserCreationSpec("Julie", "julie@example.com");
+ var marcSpec = new UserCreationSpec("Marc", "marc@example.com");
+
+ Assert.ThrowsAny(() =>
+ {
+ userCreationService.CreateListOfUsersWithIntentionalFailure(julieSpec, marcSpec);
+ });
+
+ _Output.WriteLine("Trying to retrieve our newly created users from the data store...");
+ var maybeCreatedUsers = userQueryService.GetUsers(julieSpec.Id, marcSpec.Id).ToList();
+ _Output.WriteLine(
+ "Found {0} persisted users. If this number is 0, we're all good. If this number is not 0, we have a big problem.",
+ maybeCreatedUsers.Count);
+ Assert.Equal(0, maybeCreatedUsers.Count);
+
+ //-- Demo of DbContextScope within an async flow
+ _Output.WriteLine("Trying to retrieve two users John and Jeanne sequentially in an asynchronous manner...");
+ // We're going to block on the async task here as we don't have a choice. No risk of deadlocking in any case as console apps
+ // don't have a synchronization context.
+ var usersFoundAsync = userQueryService.GetTwoUsersAsync(johnSpec.Id, jeanneSpec.Id).Result;
+ _Output.WriteLine("OK. Found {0} persisted users.", usersFoundAsync.Count);
+ Assert.Equal(2, usersFoundAsync.Count);
+ johnSpec.Equal(usersFoundAsync[0]);
+ jeanneSpec.Equal(usersFoundAsync[1]);
+
+ //-- Demo of explicit database transaction.
+ _Output.WriteLine("Trying to retrieve user John within a READ UNCOMMITTED database transaction...");
+ // You'll want to use SQL Profiler or Entity Framework Profiler to verify that the correct transaction isolation
+ // level is being used.
+ var userMaybeUncommitted = userQueryService.GetUserUncommitted(johnSpec.Id);
+ _Output.WriteLine("OK. User found: {0}", userMaybeUncommitted);
+ johnSpec.Equal(userMaybeUncommitted);
+
+ //-- Demo of disabling the DbContextScope nesting behaviour in order to force the persistence of changes made to entities
+ // This is a pretty advanced feature that you can safely ignore until you actually need it.
+ _Output.WriteLine("Will simulate sending a Welcome email to John...");
+
+ using (var parentScope = dbContextScopeFactory.Create())
+ {
+ var parentDbContext = parentScope.DbContexts.Get();
+
+ // Load John in the parent DbContext
+ var john = parentDbContext.Users.Find(johnSpec.Id);
+ _Output.WriteLine("Before calling SendWelcomeEmail(), john.WelcomeEmailSent = " +
+ john.WelcomeEmailSent);
+
+ // Now call our SendWelcomeEmail() business logic service method, which will
+ // update John in a non-nested child context
+ userEmailService.SendWelcomeEmail(johnSpec.Id);
+
+ // Verify that we can see the modifications made to John by the SendWelcomeEmail() method
+ _Output.WriteLine("After calling SendWelcomeEmail(), john.WelcomeEmailSent = " +
+ john.WelcomeEmailSent);
+
+ // Note that even though we're not calling SaveChanges() in the parent scope here, the changes
+ // made to John by SendWelcomeEmail() will remain persisted in the database as SendWelcomeEmail()
+ // forced the creation of a new DbContextScope.
+ }
+
+ //-- Demonstration of DbContextScope and parallel programming
+ _Output.WriteLine(
+ "Calculating and storing the credit score of all users in the database in parallel...");
+ userCreditScoreService.UpdateCreditScoreForAllUsers();
+ _Output.WriteLine("Done.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DbContextScope.DemoConsoleApp/DomainModel/User.cs b/src/DbContextScope.EF3.Test/DomainModel/User.cs
similarity index 91%
rename from src/DbContextScope.DemoConsoleApp/DomainModel/User.cs
rename to src/DbContextScope.EF3.Test/DomainModel/User.cs
index fdbbaec..ed9e808 100644
--- a/src/DbContextScope.DemoConsoleApp/DomainModel/User.cs
+++ b/src/DbContextScope.EF3.Test/DomainModel/User.cs
@@ -1,6 +1,6 @@
using System;
-namespace DbContextScope.DemoConsoleApp.DomainModel {
+namespace EntityFrameworkCore.DbContextScope.Test.DomainModel {
// Anemic model to keep this demo application simple.
public class User {
public Guid Id { get; set; }
diff --git a/src/DbContextScope.DemoConsoleApp/Repositories/IUserRepository.cs b/src/DbContextScope.EF3.Test/Repositories/IUserRepository.cs
similarity index 61%
rename from src/DbContextScope.DemoConsoleApp/Repositories/IUserRepository.cs
rename to src/DbContextScope.EF3.Test/Repositories/IUserRepository.cs
index b1d2129..6493fab 100644
--- a/src/DbContextScope.DemoConsoleApp/Repositories/IUserRepository.cs
+++ b/src/DbContextScope.EF3.Test/Repositories/IUserRepository.cs
@@ -1,8 +1,8 @@
using System;
using System.Threading.Tasks;
-using DbContextScope.DemoConsoleApp.DomainModel;
+using EntityFrameworkCore.DbContextScope.Test.DomainModel;
-namespace DbContextScope.DemoConsoleApp.Repositories {
+namespace EntityFrameworkCore.DbContextScope.Test.Repositories {
public interface IUserRepository {
User Get(Guid userId);
Task GetAsync(Guid userId);
diff --git a/src/DbContextScope.Test/Repositories/UserRepository.cs b/src/DbContextScope.EF3.Test/Repositories/UserRepository.cs
similarity index 93%
rename from src/DbContextScope.Test/Repositories/UserRepository.cs
rename to src/DbContextScope.EF3.Test/Repositories/UserRepository.cs
index 692dacd..fccc3af 100644
--- a/src/DbContextScope.Test/Repositories/UserRepository.cs
+++ b/src/DbContextScope.EF3.Test/Repositories/UserRepository.cs
@@ -44,12 +44,14 @@ public User Get(Guid userId) {
public Task GetAsync(Guid userId)
{
-#if NETCOREAPP2_0 || NET461
- return DbContext.Users.FindAsync(userId);
-#endif
-#if NETCOREAPP3_0
return DbContext.Users.FindAsync(userId).AsTask();
-#endif
+
+//#if NETCOREAPP2_0 || NET461
+// return DbContext.Users.FindAsync(userId);
+//#endif
+//#if NETCOREAPP3_0
+// return DbContext.Users.FindAsync(userId).AsTask();
+//#endif
}
public void Add(User user) {
diff --git a/src/DbContextScope.Test/DbContextScope.Test.csproj b/src/DbContextScope.Test/DbContextScope.Test.csproj
deleted file mode 100644
index 1bf0ac4..0000000
--- a/src/DbContextScope.Test/DbContextScope.Test.csproj
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
- net461;netcoreapp2.0;netcoreapp3.0
- false
- EntityFrameworkCore.DbContextScope.Test
- DoJo.EntityFrameworkCore.DbContextScope.Test
-
-
- NET461;NETFULL
-
-
- NETCORE;NETSTANDARD;NETCOREAPP2_0
-
-
- NETCORE;NETSTANDARD;NETCOREAPP3_0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/DbContextScope.sln b/src/DbContextScope.sln
index 1564b97..98a52e6 100644
--- a/src/DbContextScope.sln
+++ b/src/DbContextScope.sln
@@ -13,7 +13,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbContextScope", "DbContextScope\DbContextScope.csproj", "{D84F0F17-48F7-4BF6-B679-07F57A23CEA6}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DbContextScope.Test", "DbContextScope.Test\DbContextScope.Test.csproj", "{3E366ACD-5394-4D38-BBCF-7E524673A30A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbContextScope.EF2.Test", "DbContextScope.EF2.Test\DbContextScope.EF2.Test.csproj", "{A0EAD0E3-563E-4DBA-B372-6184F621D83A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbContextScope.EF3.Test", "DbContextScope.EF3.Test\DbContextScope.EF3.Test.csproj", "{CDDBFD34-CE32-419F-B778-C54EFACA5B6C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -25,10 +27,14 @@ Global
{D84F0F17-48F7-4BF6-B679-07F57A23CEA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D84F0F17-48F7-4BF6-B679-07F57A23CEA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D84F0F17-48F7-4BF6-B679-07F57A23CEA6}.Release|Any CPU.Build.0 = Release|Any CPU
- {3E366ACD-5394-4D38-BBCF-7E524673A30A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3E366ACD-5394-4D38-BBCF-7E524673A30A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3E366ACD-5394-4D38-BBCF-7E524673A30A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3E366ACD-5394-4D38-BBCF-7E524673A30A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A0EAD0E3-563E-4DBA-B372-6184F621D83A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A0EAD0E3-563E-4DBA-B372-6184F621D83A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A0EAD0E3-563E-4DBA-B372-6184F621D83A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A0EAD0E3-563E-4DBA-B372-6184F621D83A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CDDBFD34-CE32-419F-B778-C54EFACA5B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CDDBFD34-CE32-419F-B778-C54EFACA5B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CDDBFD34-CE32-419F-B778-C54EFACA5B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CDDBFD34-CE32-419F-B778-C54EFACA5B6C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/DbContextScope/DbContextScope.csproj b/src/DbContextScope/DbContextScope.csproj
index 9470df3..65d2238 100644
--- a/src/DbContextScope/DbContextScope.csproj
+++ b/src/DbContextScope/DbContextScope.csproj
@@ -1,31 +1,17 @@
- net461;netcoreapp2.0;netcoreapp3.0
+ netstandard2.0
DoJo.EntityFrameworkCore.DbContextScope
true
DoJo.EntityFrameworkCore.DbContextScope
-
- NET461;NETFULL
-
-
- NETCORE;NETSTANDARD;NETCOREAPP2_0
-
-
- NETCORE;NETSTANDARD;NETCOREAPP3_0
-
-
-
-
-
-
-
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
\ No newline at end of file
diff --git a/src/DbContextScope/Extensions/DbContextExtensions.cs b/src/DbContextScope/Extensions/DbContextExtensions.cs
index 521b4de..be771d1 100644
--- a/src/DbContextScope/Extensions/DbContextExtensions.cs
+++ b/src/DbContextScope/Extensions/DbContextExtensions.cs
@@ -1,5 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Internal;
#if NETCOREAPP2_0 || NET461
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -20,6 +22,10 @@ public static class DbContextExtensions
///
public static IStateManager GetStateManager(this DbContext context)
{
+ // seems to work for both frameworks
+ // v2.2.6
+ // v3.1.1
+ return context.GetDependencies().StateManager;
#if NETCOREAPP2_0 || NET461
return context.ChangeTracker.GetInfrastructure();
#endif