Проверьте, существует ли таблица с помощью EF Core 2.1 - PullRequest
0 голосов
/ 26 ноября 2018

В Entity Framework существование таблицы можно проверить следующим образом:

bool exists = context.Database
                 .SqlQuery<int?>(@"
                     SELECT 1 FROM sys.tables AS T
                     INNER JOIN sys.schemas AS S ON T.schema_id = S.schema_id
                     WHERE S.Name = 'SchemaName' AND T.Name = 'TableName'")
                 .SingleOrDefault() != null;

Я использую EF Core 2.1 , а метод SqlQuery не существует.

Как правильно проверить, существует ли таблица?В идеале, не пытаясь получить доступ к таблице и предполагая, что она не существует, если выдается исключение.

РЕДАКТИРОВАТЬ: Моя окончательная реализация

public bool TableExists(string tableName)
{
    return TableExists("dbo", tableName);
}

public bool TableExists(string schema, string tableName)
{
    var connection = Context.Database.GetDbConnection();

    if (connection.State.Equals(ConnectionState.Closed))
        connection.Open();

    using (var command = connection.CreateCommand())
    {
        command.CommandText = @"
            SELECT 1 FROM INFORMATION_SCHEMA.TABLES 
            WHERE TABLE_SCHEMA = @Schema
            AND TABLE_NAME = @TableName";

        var schemaParam = command.CreateParameter();
        schemaParam.ParameterName = "@Schema";
        schemaParam.Value = schema;
        command.Parameters.Add(schemaParam);

        var tableNameParam = command.CreateParameter();
        tableNameParam.ParameterName = "@TableName";
        tableNameParam.Value = tableName;
        command.Parameters.Add(tableNameParam);

        return command.ExecuteScalar() != null;
    }
}

1 Ответ

0 голосов
/ 26 ноября 2018

Существует ExecuteSqlCommand.

context.Database.ExecuteSqlCommand("...")

Однако он ограничен возвратом целого числа, указывающего, сколько строк было затронуто.Никакие строки не будут затронуты, если вы делаете SELECT, так что он действительно не работает для того, что вы хотите.

Существует также FromSql, но это работает только натаблицы, а не на уровне базы данных:

context.TableName.FromSql("SELECT ...")

Для того, что вы делаете, лучшим вариантом будет получить DbConnection из EF и создать свой собственный DbCommand.Это возвращает то, что вы ожидаете:

var conn = context.Database.GetDbConnection();
if (conn.State.Equals(ConnectionState.Closed)) await conn.OpenAsync();
using (var command = conn.CreateCommand()) {
    command.CommandText = @"
    SELECT 1 FROM sys.tables AS T
        INNER JOIN sys.schemas AS S ON T.schema_id = S.schema_id
    WHERE S.Name = 'SchemaName' AND T.Name = 'TableName'";
    var exists = await command.ExecuteScalarAsync() != null;
}

Слово предупреждения здесь: не помещайте DbConnection, который вы получаете от GetDbConnection() в оператор using, или не закрывайте его, когда высделанный.Эта связь используется для жизни этого DbContext экземпляра.Поэтому, если вы закроете его, любые последующие запросы, сделанные EF, не будут выполнены.Также возможно, что он уже был открыт перед вашим кодом, поэтому я поставил там тест, чтобы проверить, не закрыт ли он перед вызовом OpenAsync().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...