Repository: MassTransit/MassTransit

Issue #2980: Microsoft.EntityFrameworkCore 6.0 Breaking Changes
Created: 2021-11-16T07:20:54Z
Is this a bug report?
Yes
Can you also reproduce the problem with the latest version?
Yes
Environment

Dotnet version: 6.0
Operating system: Windows 10 Pro x64
IDE (Rider, VS Code, Visual Studio):  Visual Studio 2022

Steps to Reproduce

Configure SagaDbContext with Microsoft.EntityFrameworkCore 6.0
Create instance of SqlServerLockStatementProvider (or SqlLockStatementProvider).
Execute method GetRowLockStatement.

Expected Behavior
Should not throw an exception in step 3.
Actual Behavior
Throw exception in step 3.
System.MissingMethodException: Method not found: 'Microsoft.EntityFrameworkCore.Metadata.IModel Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_Model()'.
at MassTransit.EntityFrameworkCoreIntegration.SqlLockStatementProvider.GetSchemaAndTableNameAndColumnName(IDbContextDependencies dependencies, Type type)
at MassTransit.EntityFrameworkCoreIntegration.SqlLockStatementProvider.FormatLockStatement[TSaga](IDbContextDependencies context)
at MassTransit.EntityFrameworkCoreIntegration.SqlLockStatementProvider.GetRowLockStatement[TSaga](DbContext context)
Reproducible Demo
https://github.com/chjrom/MassTransit.EntityFrameworkCoreIssue

Duplicate issue #3151: "Method not found" in SqlLockStatementProvider when using EF Core >= 6.0.0
Created: 2022-02-07T12:49:17Z
Problem
The following method signature is not longer found.
IEntityType ModelExtensions.FindEntityType(IModel, Type)
There are two alternatives:

The old but obsolete extension method -> Warning: return type changed from IEntityType to IReadOnlyEntityType! Because of this, a MissingMethodException is thrown. Thank you Microsoft 😘

IReadOnlyEntityType? ModelExtensions.FindEntityType(IModel, Type)

The new method at IModel

IEntityType? IModel.FindEntityType(Type)
Seems related to #2158
Can you also reproduce the problem with the latest version?
Reproducable with

MassTransit.EntityFrameworkCore 7.3.1
Microsoft.EntityFrameworkCore 6.0.1

Environment

Dotnet version: 6.0
Operating system: Windows 10 (64bit)
IDE Visual Studio

Steps to Reproduce

Register SAGA with EntityFramworkRepository
Use MassTransit.EntityFrameworkCoreIntegration.SqlServerLockStatementProvider()

configurator.EntityFrameworkRepository(r =>
{
  r.ExistingDbContext<AppDbContext>();
  r.ConcurrencyMode = ConcurrencyMode.Pessimistic;
  r.LockStatementProvider = new MassTransit.EntityFrameworkCoreIntegration.SqlServerLockStatementProvider();
});

Emit an event that starts SAGA
Check for exception (e.g. error queue in RabbitMq)

Expected Behavior

Saga is executed properly

Actual Behavior
Exception & SAGA stops:
System.MissingMethodException: Method not found: 'Microsoft.EntityFrameworkCore.Metadata.IEntityType Microsoft.EntityFrameworkCore.ModelExtensions.FindEntityType(Microsoft.EntityFrameworkCore.Metadata.IModel, System.Type)'.
at MassTransit.EntityFrameworkCoreIntegration.SqlLockStatementProvider.GetSchemaAndTableNameAndColumnName(DbContext context, Type type)
at MassTransit.EntityFrameworkCoreIntegration.SqlLockStatementProvider.FormatLockStatement[TSaga](DbContext context)
at MassTransit.EntityFrameworkCoreIntegration.SqlLockStatementProvider.GetRowLockStatement[TSaga](DbContext context)
at MassTransit.EntityFrameworkCoreIntegration.Saga.PessimisticLoadQueryExecutor`1.GetLockStatement(DbContext dbContext)
at MassTransit.EntityFrameworkCoreIntegration.Saga.PessimisticLoadQueryExecutor`1.Load(DbContext dbContext, Guid correlationId, CancellationToken cancellationToken)
at MassTransit.EntityFrameworkCoreIntegration.Saga.PessimisticSagaRepositoryLockStrategy`1.Load(DbContext context, Guid correlationId, CancellationToken cancellationToken)
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.DbContextSagaRepositoryContext`2.Load(Guid correlationId)
at MassTransit.Saga.SendSagaPipe`2.Send(SagaRepositoryContext`2 context)
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.<>c__DisplayClass5_0`1.<<Send>b__1>d.MoveNext()
--- End of stack trace from previous location ---
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.<>c__DisplayClass8_0.<<WithinTransaction>g__Create|0>d.MoveNext()
--- End of stack trace from previous location ---
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.WithinTransaction[T](DbContext context, CancellationToken cancellationToken, Func`1 callback)
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.WithinTransaction[T](DbContext context, CancellationToken cancellationToken, Func`1 callback)
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.WithinTransaction[T](DbContext context, CancellationToken cancellationToken, Func`1 callback)
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.Send[T](ConsumeContext`1 context, IPipe`1 next)
at MassTransit.EntityFrameworkCoreIntegration.Saga.Context.EntityFrameworkSagaRepositoryContextFactory`1.Send[T](ConsumeContext`1 context, IPipe`1 next)
at MassTransit.ExtensionsDependencyInjectionIntegration.ScopeProviders.DependencyInjectionSagaRepositoryContextFactory`1.<>c__DisplayClass6_0`1.<<Send>g__CreateScope|0>d.MoveNext()
--- End of stack trace from previous location ---
at MassTransit.ExtensionsDependencyInjectionIntegration.ScopeProviders.DependencyInjectionSagaRepositoryContextFactory`1.<>c__DisplayClass6_0`1.<<Send>g__CreateScope|0>d.MoveNext()
--- End of stack trace from previous location ---
at MassTransit.Saga.Pipeline.Filters.CorrelatedSagaFilter`2.GreenPipes.IFilter<MassTransit.ConsumeContext<TMessage>>.Send(ConsumeContext`1 context, IPipe`1 next)
at MassTransit.Saga.Pipeline.Filters.CorrelatedSagaFilter`2.GreenPipes.IFilter<MassTransit.ConsumeContext<TMessage>>.Send(ConsumeContext`1 context, IPipe`1 next)
at GreenPipes.Filters.TeeFilter`1.<>c__DisplayClass5_0.<<Send>g__SendAsync|1>d.MoveNext()
--- End of stack trace from previous location ---
at GreenPipes.Filters.OutputPipeFilter`2.SendToOutput(IPipe`1 next, TOutput pipeContext)
at GreenPipes.Filters.OutputPipeFilter`2.SendToOutput(IPipe`1 next, TOutput pipeContext)
at GreenPipes.Filters.DynamicFilter`1.<>c__DisplayClass10_0.<<Send>g__SendAsync|0>d.MoveNext()
--- End of stack trace from previous location ---
at MassTransit.Pipeline.Filters.DeserializeFilter.Send(ReceiveContext context, IPipe`1 next)
at GreenPipes.Filters.RescueFilter`2.GreenPipes.IFilter<TContext>.Send(TContext context, IPipe`1 next)

Closing comment (2022-02-07T12:58:05Z): Duplicate. #2980