【问题标题】:MassTransit saga persistance with Entity Framework and MySQL实体框架和 MySQL 的 MassTransit 传奇持久性
【发布时间】:2017-10-19 23:59:06
【问题描述】:

我正在使用 MassTransit(使用 RabbitMQ)和 Automatonymous 开发一个传奇。我使用 EntityFramework 作为我的存储引擎和 MySQL 作为我的数据库。每次我尝试运行 saga 并将其状态存储在数据库中时,EF 和 MySQL 的组合都会引发异常。使用this 示例应用程序并使用 MySQL 数据库的连接字符串可以重现该问题。抛出的确切异常是:

System.Data.SqlClient.SqlException (0x80131904):网络相关或 建立连接时发生特定于实例的错误 SQL 服务器。服务器未找到或无法访问。核实 实例名称正确且 SQL Server 配置为 允许远程连接。 (提供者:命名管道提供者,错误:40 - 无法打开与 SQL Server 的连接)---> Syste m.ComponentModel.Win32Exception (0x80004005): 系统找不到 指定的文件 System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity 身份、SqlConnectionString 连接选项、SqlCredential 凭证、对象 providerInfo、字符串 newPassword、SecureString newSecurePassword、布尔重定向用户实例、SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool 池、字符串 accessToken、布尔型 applyTra nsientFaultHandling)在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions 选项,DbConnectionPoolKey poolKey,对象 poolGroupProviderInfo, DbConnectionPool 池,DbConnection 拥有连接, DbConnectionOptions 用户选项)在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool 池,DbConnection owningObject,DbConnectionOptions 选项, DbConnectionPoolKey poolKey, DbConnectionOption s userOptions) at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal 旧连接)在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal 旧连接)在 System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOption ns userOptions,DbConnectionInternal& 连接)在 System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject,TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 重试,DbConnectionOptions userOptions, DbConnectionInternal oldConnection, Db ConnectionInternal&连接)在 System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection 外部连接,DbConnectionFactory 连接工厂, TaskCompletionSource1 retry, DbConnectionOptions use rOptions) at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 重试,DbConnectionOptions userOptions) 在 System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 重试)在 System.Data.SqlClient.SqlConnection.Open() 在 System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.b__36(DbConnection t,DbConnectionInterceptionContext c) 在 System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action2 操作,TInterceptionContext 拦截上下文, Action3 executing, Action3 执行)在 System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection 连接,DbInterceptionContext 拦截上下文)在 System.Data.Entity.SqlServer.SqlProviderServices.c__DisplayClass33.b__32() 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.c__DisplayClass1.b__0() 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func1 operation) at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation) at System.Data.Entity.SqlServer.SqlProviderServices.UsingConnection(DbConnection sqlConnection, Action1 act) 在 System.Data.Entity.SqlServer.SqlProviderServices.UsingMasterConnection(DbConnection sqlConnection, Action1 act) at System.Data.Entity.SqlServer.SqlProviderServices.CreateDatabaseFromScript(Nullable1 commandTimeout, DbConnection sqlConnection, 字符串 createDatabaseScript) 在 System.Data.Entity.SqlServer.SqlProviderServices.DbCreateDatabase(DbConnection 连接,Nullable1 commandTimeout, StoreItemCollection storeItemCollection) at System.Data.Entity.Core.Common.DbProviderServices.CreateDatabase(DbConnection connection, Nullable1 命令超时,StoreItemCollection storeItemCollection) 在 System.Data.Entity.Core.Objects.ObjectContext.CreateDatabase() 在 System.Data.Entity.Migrations.Utilities.DatabaseCreator.Create(DbConnection 连接)在 System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(操作 mustSucceedToKeepDatabase) 在 System.Data.Entity.Migrations.DbMigrator.Update(字符串 目标迁移)在 System.Data.Entity.Internal.DatabaseCreator.CreateDatabase(InternalContext internalContext, Func3 createMigrator, ObjectContext objectContext) at System.Data.Entity.Internal.InternalContext.CreateDatabase(ObjectContext objectContext, DatabaseExistenceState existenceState) at System.Data.Entity.Database.Create(DatabaseExistenceState existenceState) at System.Data.Entity.CreateDatabaseIfNotExists1.InitializeDatabase(TContext 上下文)在 System.Data.Entity.Internal.InternalContext.c__DisplayClassf1.<CreateInitializationAction>b__e() at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action) at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() at System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c) at System.Data.Entity.Internal.RetryAction1.PerformAction(TInput 输入)在 System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action1 action) at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase() at System.Data.Entity.Internal.LazyInternalContext.get_ObjectContext() at System.Data.Entity.Database.BeginTransaction(IsolationLevel isolationLevel) at MassTransit.EntityFrameworkIntegration.Saga.EntityFrameworkSagaRepository1.d__81.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at MassTransit.Saga.Pipeline.Filters.QuerySagaFilter2.>-Send>d__6.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 MassTransit.Saga.Pipeline.Filters.QuerySagaFilter2.<MassTransit-Pipeline-IFilter<MassTransit-ConsumeContext<TMessage>>-Send>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at MassTransit.Saga.Pipeline.Filters.CorrelationIdMessageFilter1.d__3.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 MassTransit.Pipeline.Filters.TeeConsumeFilter1.<>c__DisplayClass7_0.<<Send>b__0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at MassTransit.Pipeline.Filters.TeeConsumeFilter1.d__7.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 MassTransit.Pipeline.Filters.MessageConsumeFilter1.<MassTransit-Pipeline-IFilter<MassTransit-ConsumeContext>-Send>d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at MassTransit.Pipeline.Filters.MessageConsumeFilter1.-Send>d__7.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 MassTransit.Pipeline.Filters.DeserializeFilter.d__4.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 MassTransit.Pipeline.Filters.RescueReceiveContextFilter`1.-Send>d__5.MoveNext() ClientConnectionId:00000000-0000-0000-0000-000000000000 错误 编号:2,状态:0,等级:20

如果我使用与 VS 2015 一起安装的本地数据库而不是 MySQL,那么它工作得非常好。它也适用于内存存储。即使异常说找不到服务器,我也可以确认它存在并且可以访问,因为示例应用程序在选择连接字符串时首先进行检查并且成功:

using (var connection = new SqlConnection(connectionString))
{
    // It worked, we can save this as our connection string
    return connectionString;
}

问题是否可能是因为它试图使用 SqlClient 访问 MySQL 数据库?

我正在使用 MySQL Server 5.7、EF 6.1.3、MassTransit 3.5.7 和 Automatonymous 3.5.11。

【问题讨论】:

  • 确切的例外是什么?
  • 我更新了这个问题,但有例外。

标签: c# mysql entity-framework masstransit automatonymous


【解决方案1】:

这不是 MassTransit 问题,而是实体框架问题。应该是这样的:

如何在 MySQL 中使用实体框架。

你的异常清楚地表明:System.Data.SqlClient 正在抛出它。这是 SQL Server 客户端。它还说:

无法打开与 SQL Server 的连接

如何配置EF和MySQL可以参考documentation。一般情况下,需要安装MySql.Data.EntityNuGet包并告诉EF你使用的是MySQL,然后配置正确的连接字符串:

<connectionStrings>
    <add name="MyContext" providerName="MySql.Data.MySqlClient"
        connectionString="server=localhost;port=3306;database=mycontext;uid=root;password=********"/>
</connectionStrings>
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
    <providers>
        <provider invariantName="MySql.Data.MySqlClient"
            type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"/>
        <provider invariantName="System.Data.SqlClient"
            type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
    </providers>
</entityFramework>

【讨论】:

  • 按照建议编辑 app.config 后,我仍然需要更改示例代码。我不必将连接字符串传递给 SagaDbContext 类的构造函数,而是必须传递连接字符串的名称(“MyContext”)。然后它确实与我的 MySQL 数据库建立了连接。那时我遇到了另一个异常,抱怨应该存储 saga 状态的表不存在。因此,为了让 saga 充分发挥作用,我必须添加一个 DbContext 类和一个迁移以在数据库中创建表,否则 MassTransit 不会自己创建它。
  • 我明白了。这可能是由 EF API 更改引起的,因为 SagaDbContext 实现了 DbContext 基类的所有构造函数,并且唯一获取连接字符串的构造函数使用连接字符串的名称。 github.com/MassTransit/MassTransit/blob/develop/src/Persistence/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多