broodjebal74
broodjebal74

Reputation: 11

State parameter of ExecuteInTransactionAsync unclear

I'm curious how I should use the state parameter of the ExecuteInTransactionAsync method of Entity Framework Core.

I tried to read the docs of Microsoft (https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.executionstrategyextensions.executeintransactionasync?view=efcore-9.0) but it is still unclear to me what they mean with:

The state that will be passed to the operation.

You can also just add a variable above the ExecuteInTransactionAsync method and use that variable inside the method. Are there negatives or positives about one of the ways?

Example

Option 1 with state:

using var db = new BloggingContext();
var strategy = db.Database.CreateExecutionStrategy();

var blogToAdd = new Blog { Url = "http://blogs.msdn.com/dotnet" };
db.Blogs.Add(blogToAdd);

await strategy.ExecuteInTransactionAsync(
    db, // Passing the DbContext as "state"
    operation: (context, cancellationToken) => context.SaveChangesAsync(acceptAllChangesOnSuccess: false, cancellationToken),
    verifySucceeded: (context, cancellationToken) => context.Blogs.AsNoTracking().AnyAsync(b => b.BlogId == blogToAdd.BlogId, cancellationToken));

db.ChangeTracker.AcceptAllChanges();

Option 2 without state:

using var context = new BloggingContext();
var strategy = context.Database.CreateExecutionStrategy();

var blogToAdd = new Blog { Url = "http://blogs.msdn.com/dotnet" };
context.Blogs.Add(blogToAdd);

await strategy.ExecuteInTransactionAsync(
    operation: (cancellationToken) => context.SaveChangesAsync(acceptAllChangesOnSuccess: false, cancellationToken),
    verifySucceeded: (cancellationToken) => context.Blogs.AsNoTracking().AnyAsync(b => b.BlogId == blogToAdd.BlogId, cancellationToken));

context.ChangeTracker.AcceptAllChanges();

Upvotes: 1

Views: 47

Answers (2)

Gert Arnold
Gert Arnold

Reputation: 109245

The first call (with state) is preferred—theoretically. Just because it is a more "pure" method call. I.e. it starts an operation that is less dependent of side effects, because the context (db) is entered as well. The started process is not dependent of the external state db, while in the second example it depends on the external context variable.

In C# this is all just marginally relevant theory. Objects are passed as reference, so in either example the context could be changed concurrently by any parallel process. As we can safely assume that doesn't happen, practically there's no difference.

Upvotes: 0

Brando Zhang
Brando Zhang

Reputation: 28257

In my opinion, both of the two codes are the same, the only difference is the option one is pass a DB to the ExecuteInTransactionAsync, the option two is use the context which from the delegates.

They are both using the same dbcontext which is the same.

Upvotes: 0

Related Questions