Entity Framework 핵심 마이그레이션 명령을 사용할 때 데이터베이스 파일을 연결할 수 없습니다.

entity-framework-core

문제

마이그레이션 데이터베이스에 EntityFramework Core 명령을 사용하고 있습니다. 내가 사용하고있는 명령어는 다음과 같다 : dnx. 마이그레이션이 적용됩니다. 문제는 연결 문자열에 AttachDbFileName을 지정할 때 다음 오류가 나타납니다. 데이터베이스 파일을 데이터베이스 xxxxxxx로 연결할 수 없습니다. 이것은 사용중인 연결 문자열입니다. 데이터 원본 = (LocalDB) \ mssqllocaldb; 통합 보안 = True; 초기 카탈로그 = EfGetStarted2; AttachDbFileName = D : \ EfGetStarted2.mdf

db 파일을 다른 위치에 연결하는 방법을 도와주세요. 감사

수락 된 답변

EF 코어는 AttachDbFileName에 문제가 있거나 전혀 처리하지 못합니다.

  • EnsureDeleted 는 데이터베이스 이름을 master로 변경하지만 AttachDbFileName 값을 유지하므로 master 데이터베이스를 다른 파일에 연결할 수 없기 때문에 오류가 발생합니다.
  • EnsureCreated 는 제공된 AttachDbFileName 값을 사용하여 연결을 엽니 다. 생성하려는 데이터베이스 파일이 아직 존재하지 않으므로 오류가 발생합니다.

EF6에는 이러한 사용 사례를 처리 할 수있는 몇 가지 논리가 있습니다. SqlProviderServices.DbCreateDatabase 참조하십시오.

해결 방법으로 이러한 시나리오를 처리하기 위해 몇 가지 해킹 코드를 작성했습니다.

public static void EnsureDatabase(this DbContext context, bool reset = false)
{
    if (context == null)
        throw new ArgumentNullException(nameof(context));

    if (reset)
    {
        try
        {
            context.Database.EnsureDeleted();
        }
        catch (SqlException ex) when (ex.Number == 1801)
        {
            // HACK: EF doesn't interpret error 1801 as already existing database
            ExecuteStatement(context, BuildDropStatement);
        }
        catch (SqlException ex) when (ex.Number == 1832)
        {
            // nothing to do here (see below)
        }
    }

    try
    {
        context.Database.EnsureCreated();
    }
    catch (SqlException ex) when (ex.Number == 1832)
    {
        // HACK: EF doesn't interpret error 1832 as non existing database
        ExecuteStatement(context, BuildCreateStatement);

        // this takes some time (?)
        WaitDatabaseCreated(context);

        // re-ensure create for tables and stuff
        context.Database.EnsureCreated();
    }
}

private static void WaitDatabaseCreated(DbContext context)
{
    var timeout = DateTime.UtcNow + TimeSpan.FromMinutes(1);

    while (true)
    {
        try
        {
            context.Database.OpenConnection();
            context.Database.CloseConnection();
        }
        catch (SqlException)
        {
            if (DateTime.UtcNow > timeout)
                throw;
            continue;
        }
        break;
    }
}

private static void ExecuteStatement(DbContext context, Func<SqlConnectionStringBuilder, string> statement)
{
    var builder = new SqlConnectionStringBuilder(context.Database.GetDbConnection().ConnectionString);

    using (var connection = new SqlConnection($"Data Source={builder.DataSource}"))
    {
        connection.Open();

        using (var command = connection.CreateCommand())
        {
            command.CommandText = statement(builder);
            command.ExecuteNonQuery();
        }
    }
}

private static string BuildDropStatement(SqlConnectionStringBuilder builder)
{
    var database = builder.InitialCatalog;

    return $"drop database [{database}]";
}

private static string BuildCreateStatement(SqlConnectionStringBuilder builder)
{
    var database = builder.InitialCatalog;

    var datafile = builder.AttachDBFilename;
    var dataname = Path.GetFileNameWithoutExtension(datafile);

    var logfile = Path.ChangeExtension(datafile, ".ldf");
    var logname = dataname + "_log";

    return $"create database [{database}] on primary (name = '{dataname}', filename = '{datafile}') log on (name = '{logname}', filename = '{logfile}')";
}

좋은 것은 아니지만 어쨌든 통합 테스트에 사용하고 있습니다. EF 마이그레이션을 사용하는 "실제"시나리오의 경우 이동해야하지만 어쩌면이 문제의 근본 원인은 동일합니다 ...

최신 정보

다음 버전에는 AttachDBFilename에 대한 지원 이 포함됩니다.


인기 답변

EfGetStarted2라는 데이터베이스에 다른 * .mdf 파일이 이미 연결되어있을 수 있습니다 ... 해당 데이터베이스를 삭제하거나 분리 한 다음 다시 시도하십시오.

LocalDB 사용자가 경로에 대한 올바른 권한을 가지고 있지 않아 실행 중일 때 문제가 발생할 수도 있습니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.