Reputation: 11
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
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
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