dotnet / EntityFramework.Docs

Documentation for Entity Framework Core and Entity Framework 6
https://docs.microsoft.com/ef/
Creative Commons Attribution 4.0 International
1.56k stars 1.94k forks source link

Doc does not address the most common use-case, when DbContext is injected #4710

Open mikerains-valorem opened 1 month ago

mikerains-valorem commented 1 month ago

Type of issue

Missing information

Description

Where the documentation describes using System.Transactions for Ambient transaction support, it only discusses when DbContext is constructed inside the TransactiopnScope using block. But this rarely happens in the real world.

In the real world, DbContext is injected into the class, so it and its SqlConnection are created before the using TransactionScope. In this case, it is unclear if the DbContext's SqlConnection will be enlisted in the TransactionScope or CommittableTransaction.

The Documentation has 2 examples.

First documentation Example:

using (var scope = new TransactionScope(
           TransactionScopeOption.Required,
           new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
{
    using var connection = new SqlConnection(connectionString);
    connection.Open();

    try
    {
        // Run raw ADO.NET command in the transaction
        var command = connection.CreateCommand();
        command.CommandText = "DELETE FROM dbo.Blogs";
        command.ExecuteNonQuery();

        // Run an EF Core command in the transaction
        var options = new DbContextOptionsBuilder<BloggingContext>()
            .UseSqlServer(connection)
            .Options;
        using (var context = new BloggingContext(options))
        {
            context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
            context.SaveChanges();
        }

Question: Here BloggingContext is created form a connection that was created and opened INSIDE A TransactionScope. Will a DbContext injected into the class participate in the TransactionScope, since it is created with a SqlConnection BEFORE the method which creates the TransactionScope executes?

Second documentation example:

using (var transaction = new CommittableTransaction(
           new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
{
    var connection = new SqlConnection(connectionString);

    try
    {
        var options = new DbContextOptionsBuilder<BloggingContext>()
            .UseSqlServer(connection)
            .Options;

        using (var context = new BloggingContext(options))
        {
            context.Database.OpenConnection();
            context.Database.EnlistTransaction(transaction);

Question: When DbContext is injected, can the client code call context.Database.EnlistTransaction(transaction) and expect the DbContext.SaveChanges() to participate in the CommittableTransaction?

Page URL

https://learn.microsoft.com/en-us/ef/core/saving/transactions

Content source URL

https://github.com/dotnet/EntityFramework.Docs/blob/main/entity-framework/core/saving/transactions.md

Document Version Independent Id

cf56babd-def0-d76e-8eee-e33341b6a009

Article author

@roji