dotnet / dotnet/EntityFramework.Docs

Change the "Cross-context transaction (relational databases only)"

Open
#471 1 comment 1 reaction 0 assignees View on GitHub
area-transactions
Dominant language
Mermaid
Stars
1.7k
Forks
2k
Avg merge
7d 23h
Merged PRs (30d)
16

Description

Moved from [aspnet/Docs#4220](https://github.com/aspnet/Docs/issues/4220). Filed by @Ciantic, pertaining to the following doc:
https://docs.microsoft.com/ef/core/saving/transactions

I propose to change the section "Cross-context transaction (relational databases only)".

Current approach as it now stands suggest to change the super class constructor signature of DbContext, this can be cumbersome since everyone who develops DbContext super classes need to change their constructors.

With my approach below it is not required to refactor your precious DbContexts which may be separated in different projects etc. The super classes of DbContext can be "regular" and have a DbContextOptions as a argument as in every other example. The trick is then to provide the connection to shared contexts using the regular `AddDbContext` configuration.

1. Create a simple DI class that wraps the shared connection e.g.

```C#
///
/// This allows to share a DbConnection within a scope, e.g. between DbContexts so they can perform transactions
///
public class DbContextConnectionConfiguration : IDisposable
{
private readonly DbConnection _dbConnection;
private readonly Action _configuration;
private readonly bool _dispose;

public DbContextConnectionConfiguration(DbConnection dbConnection, Action configuration, bool dispose = true)
{
_dbConnection = dbConnection;
_configuration = configuration;
_dispose = dispose;
}

public void Configure(DbContextOptionsBuilder optionsBuilder)
{
_configuration(_dbConnection, optionsBuilder);
}

public void Dispose()
{
if (_dispose) {
_dbConnection.Dispose();
}
}
}
```

Now only thing required is to inject this to `AddDbContext` calls in *Startup.cs*:

```C#
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped(t => new DbContextConnectionConfiguration(
new SqliteConnection(Configuration.GetConnectionString("Default")),
(c, o) => o.UseSqlite(c)
));
services.AddDbContext((s, o) =>
{
s.GetService().Configure(o);
});
services.AddDbContext((s, o) =>
{
s.GetService().Configure(o);
});
}
```

That's it, there is no need to refactor your DbContext's just to share a connection.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.