Określona nazwa instancji LocalDB jest nieprawidłowa: można tworzyć migracje, ale nie można ich uruchamiać

Dec 01 2020

Stworzyłem nowe rozwiązanie XAF Blazor i mogłem je uruchomić, aby utworzyć bazę danych. Następnie dodałem migrację bazy danych zgodnie z tym pytaniem Jednak kiedy idę uruchomić migrację z poziomu menedżera pakietów, otrzymuję

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.
)

To pytanie nie jest powtórzeniem tego pytania dotyczącego łączenia się z serwerem SQL, ponieważ program mógł uzyskać dostęp do bazy danych przed utworzeniem migracji.

[Aktualizacja]

Kod to

    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; }
        }

[Aktualizacja]

Próbowałem skomentować atrybut Dev Express TypesInfoInitializer Próbowałem dodać następujące, ale nie wykonuje (błąd nie zgłasza) Natomiast jeśli wstawię błąd w metodzie IDesignTimeDbContextFactory, wyrzuci

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);
    }
}

Metoda ExamBuddyContextFactory nie jest wykonywana

[Aktualizacja]

Kiedy edytuję parametry połączenia, aby używać tylko 1 odwrotnego ukośnika, widzę następujące komunikaty w programie Visual Studio 2019

Tak więc migracja zostanie wygenerowana z podwójnym ukośnikiem odwrotnym w ciągu połączenia, ale nie zostanie uruchomiona.

Odpowiedzi

1 IvanStoev Dec 03 2020 at 19:30

Komunikat o wyjątku informuje o problemie

Określona nazwa instancji LocalDB jest nieprawidłowa

Nieprawidłowa część to podwójny ukośnik odwrotny (localdb)\\mssqllocaldbwewnątrz literału ciągu C # dosłownie

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

Rzeczywista nazwa to (localdb)\mssqllocaldb(pojedynczy lewy ukośnik), więc popraw ją lub usuń przedrostek w postaci dosłownego ciągu @.

To wszystko są tylko standardowe reguły ciągów C #, nie ma nic specjalnego do omówienia. To dlaczego

Potrafisz tworzyć migracje, ale ich nie uruchamiać?

Dzieje się tak, ponieważ Add-Migrationpolecenie nie próbuje połączyć się z bazą danych, a połączenie z bazą danych jest inicjowane leniwie tylko w razie potrzeby, dlatego nieprawidłowe parametry połączenia nie są wykrywane. Polecenie nadal musi utworzyć DbContextwystąpienie, aby uzyskać dostęp do modelu , a kontekst musi być skonfigurowany dla określonego typu dostawcy bazy danych (ponieważ EF Core tworzy oddzielny model dla każdego typu dostawcy bazy danych), ale poza tym nie ma z nim nic wspólnego rzeczywista baza danych.

Jednak Update-Databasepolecenie najwyraźniej wymaga połączenia z bazą danych, a także Remove-Migrationpolecenia, które musi sprawdzić, czy migracja została już zastosowana. Dlatego te polecenia zawodzą, ale się powiodą Add-Migration.

Możesz to łatwo sprawdzić, podając fałszywe nieprawidłowe parametry połączenia, takie jak

optionsBuilder.UseSqlServer("Blah")'

i obserwuj dokładnie takie same zachowania, jak w PO.