【问题标题】:Check if a table exists using EF Core 2.1使用 EF Core 2.1 检查表是否存在
【发布时间】:2018-11-27 04:23:32
【问题描述】:

在实体框架中,可以通过这种方式检查表的存在:

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

【问题讨论】:

  • 你能扩展is not valid吗?
  • 你试过FromSql吗?
  • 这个问题是关于“开放查询”的一般问题,还是严格意义上的表存在检查?
  • @JohnB 该方法在 EF Core 中不存在。

标签: c# entity-framework entity-framework-core


【解决方案1】:

ExecuteSqlCommand

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

但是,它仅限于返回一个整数,指示有多少行受到影响。如果您正在执行 SELECT,则不会影响任何行,因此它并不能真正满足您的需求。

还有FromSql,但仅适用于表,不适用于数据库级别:

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

对于您正在做的事情,更好的选择是从 EF 获取 DbConnection,然后创建您自己的 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;
}

这里有一句警告:不要将你从GetDbConnection() 得到的DbConnection 放在using 语句中,或者在完成后关闭它。该连接用于该DbContext 实例的生命周期。因此,如果您关闭它,EF 稍后发出的任何请求都将失败。也有可能它在你的代码之前已经打开了,这就是为什么我在调用 OpenAsync() 之前在其中进行测试以查看它是否已关闭。

【讨论】:

  • 如何使用 FromSql 检查表是否存在?据我所知,它需要一个实体来映射,所以我需要为信息模式构建一个 Dto 吗?
  • 您需要知道该表才能使用FromSql,所以我认为您不能使用它来确定表是否存在。
  • 现在我回到办公室,可以做一些测试。我找到了另一种方法。我已经更新了我的答案。
  • 感谢 Gabriel,我还用我的最终实现编辑了我的问题。
  • Nit:关闭连接是好的(它将被重新打开),处理连接(根据使用)不是,因为未来的打开调用将失败..事实上,确保连接是关闭可能会“更好”以立即将连接返回到池中。
猜你喜欢
  • 2021-10-06
  • 2020-03-29
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2019-03-16
  • 2023-04-09
  • 1970-01-01
  • 2018-12-05
相关资源
最近更新 更多