指定されたLocalDBインスタンス名が無効です:移行を作成できますが、実行できません

Dec 01 2020

新しいXAFBlazorソリューションを作成し、それを実行してデータベースを作成することができました。次に、この質問に従ってデータベースの移行を追加しました。ただし、パッケージマネージャー内から移行を実行すると、次のようになります。

Microsoft.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SNI_PN11, error: 50 - Local Database Runtime error occurred. Specified LocalDB instance name is invalid.
)
 ---> System.ComponentModel.Win32Exception (0x89C5011B): Unknown error (0x89c5011b)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover, SqlAuthenticationMethod authType)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling, String accessToken, DbConnectionPool pool)
   at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass18_0.<Exists>b__0(DateTime giveUp)
   at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c__DisplayClass12_0`2.<Execute>b__0(DbContext c, TState s)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation, Func`2 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists(Boolean retryOnNotExists)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:00000000-0000-0000-0000-000000000000
Error Number:-1983577829,State:0,Class:20
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. 
(provider: SNI_PN11, error: 50 - Local Database Runtime error occurred. Specified LocalDB instance name is invalid.
)

移行を作成する前にプログラムがデータベースにアクセスできたため、この質問はSQLServerへの接続に関するこの質問と重複していません。

[更新]

コードは

    using DevExpress.ExpressApp.EFCore.Updating;
    using Microsoft.EntityFrameworkCore;
    using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;
    using DevExpress.Persistent.BaseImpl.EF;
    using DevExpress.ExpressApp.Design;
    using DevExpress.ExpressApp.EFCore.DesignTime;
    using DevExpress.Persistent.Base;
    using Microsoft.EntityFrameworkCore.Design;
    namespace ExamBuddy.Module.BusinessObjects {
        public class ExamBuddyContextInitializer : DbContextTypesInfoInitializerBase {
            protected override DbContext CreateDbContext() {
                var builder = new DbContextOptionsBuilder<ExamBuddyEFCoreDbContext>()
                    .UseSqlServer(@";");
                return new ExamBuddyEFCoreDbContext(builder.Options);
            }
        }
        public class ExamBuddyContextFactory : IDesignTimeDbContextFactory<ExamBuddyEFCoreDbContext>
        {
            public ExamBuddyEFCoreDbContext CreateDbContext(string[] args)
            {
                var optionsBuilder = new DbContextOptionsBuilder<ExamBuddyEFCoreDbContext>();
                optionsBuilder.UseSqlServer(@"Integrated Security=SSPI;MultipleActiveResultSets=true;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=ExamBuddy;ConnectRetryCount=0;");
                return new ExamBuddyEFCoreDbContext(optionsBuilder.Options);
            }
        }
        [TypesInfoInitializer(typeof(ExamBuddyContextInitializer))]
        public class ExamBuddyEFCoreDbContext : DbContext {
            public ExamBuddyEFCoreDbContext(DbContextOptions<ExamBuddyEFCoreDbContext> options) : base(options) {
                 
            }
            public DbSet<ModuleInfo> ModulesInfo { get; set; }
            public DbSet<ModelDifference> ModelDifferences { get; set; }
            public DbSet<ModelDifferenceAspect> ModelDifferenceAspects { get; set; }
            public DbSet<PermissionPolicyRole> Roles { get; set; }
            public DbSet<PermissionPolicyRoleBase> RolesBase { get; set; }
            public DbSet<PermissionPolicyUser> Users { get; set; }
        }

[更新]

以下に追加しようとしたDevExpress TypesInfoInitializer属性をコメントアウトしようとしましたが、実行されません(エラーはスローされません)。一方、IDesignTimeDbContextFactoryメソッドにエラーを入力すると、スローされます。

public class MigrationsContextFactory : IDbContextFactory<ExamBuddyEFCoreDbContext>
{
    public ExamBuddyEFCoreDbContext CreateDbContext()
    {
        throw new Exception("In Migration Context");
        var optionsBuilder = new DbContextOptionsBuilder<ExamBuddyEFCoreDbContext>();
        optionsBuilder.UseSqlServer(@"Integrated Security=SSPI;MultipleActiveResultSets=true;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=ExamBuddy;ConnectRetryCount=0;");
        return new ExamBuddyEFCoreDbContext(optionsBuilder.Options);
    }
}

ExamBuddyContextFactoryメソッドは実行されます

[更新]

バックスラッシュを1つだけ使用するように接続文字列を編集すると、Visual Studio2019で次のメッセージが表示されます。

したがって、移行は接続文字列の二重バックスラッシュで生成されますが、実行されません。

回答

1 IvanStoev Dec 03 2020 at 19:30

例外メッセージはあなたに問題を伝えています

指定されたLocalDBインスタンス名が無効です

無効な部分は(localdb)\\mssqllocaldb、C#の逐語的な文字列リテラル内の二重円記号です

optionsBuilder.UseSqlServer(
    @"Data Source=(localdb)\\mssqllocaldb;Integrated Security=SSPI;MultipleActiveResultSets=true;Pooling=false;Initial Catalog=ExamBuddy;ConnectRetryCount=0;");
//  ^                       ^

実際の名前は(localdb)\mssqllocaldb(単一の円記号)なので、それを修正するか、逐語的な文字列プレフィックスを削除します@

これらはすべて標準のC#文字列ルールであり、特別な説明はありません。それでなんで

移行を作成することはできますが、実行することはできませんか?

これは、Add-Migrationコマンドがデータベースへの接続を試行せず、データベース接続が必要な場合にのみ遅延初期化されるため、無効な接続文字列が検出されないためです。コマンドDbContextはモデルにアクセスするためにインスタンスを作成する必要があり、コンテキストは特定のデータベースプロバイダータイプ用に構成する必要があります(EF Coreはデータベースプロバイダータイプごとに個別のモデルを作成するため)が、それ以外は何の関係もありません実際のデータベース。

ただし、Update-Databaseコマンドには明らかにデータベース接続Remove-Migrationが必要であり、移行がすでに適用されているかどうかを確認する必要があるコマンドも必要です。そのため、これらのコマンドはAdd-Migration成功しながら失敗します。

次のような偽の無効な接続文字列を指定することで、簡単に確認できます。

optionsBuilder.UseSqlServer("Blah")'

OPとまったく同じ動作を観察します。