实体框架 - 如何检查表是否存在?

问题描述 投票:0回答:8

我使用实体框架和代码优先方法。基类 DbContext 具有创建和删除数据库以及检查数据库是否存在的功能。

我想检查一个特殊的表(实体)是否存在。是否可以使用框架实现或者我需要编写自定义方法?如果我需要编写自己的实现,最通用的方法是什么?

感谢您的帮助。

c# sql ef-code-first entity-framework-4.1
8个回答
43
投票

如果您需要检查表是否存在,您必须调用自定义 SQL 代码:

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;

表名称默认定义为派生上下文中公开的

DbSet
的名称,但默认名称可以通过 Fluent API 的
ToTable
方法或
Table
数据注释进行覆盖。

以通用方式执行此操作并不是代码优先方法中所设想的。这将需要浏览元数据并手动探索实体映射到哪个表 - 这可能非常复杂,因为实体可以映射到多个表。代码优先不提供对元数据的访问。您必须将

DbContext
转换为
ObjectContext
并浏览
MetadataWorkspace

编辑:

要将

DbContext
转换为
ObjectContext
,请使用以下命令:

ObjectContext objContext = ((IObjectContextAdapter)dbContext).ObjectContext;

6
投票

我无法对上一篇文章添加评论。我正在使用 SQL Compact,但我不知道表的架构。我正在使用此代码来检查表,它与上一篇文章中的代码非常相同,但它适用于任何表。

    /// <summary>
    /// Check if data table is exist in application
    /// </summary>
    /// <typeparam name="T">Class of data table to check</typeparam>
    /// <param name="db">DB Object</param>
    public static bool CheckTableExists<T>(this ModelLocker db) where T : class
    {
        try
        {
            db.Set<T>().Count();
            return true;

        }
        catch (Exception)
        {
            return false;
        }
    }

4
投票

另一种方法;它不像 Ladislav 那样高效,但它不依赖于 SQL Server(经过编辑以添加Where子句来解决性能问题):

bool CheckTableExists()
{
    try
    {
        context.YourTable.Where(s => s.<yourKeyField> = <impossible value>).Count();
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}

2
投票

假设:SQL Server

查询

DbSet
时捕获任何旧异常并不意味着该表不存在。

查询不存在表的

DbSet
将抛出
EntityCommandExecutionException
以及类型为
SqlException
的内部异常。该内部异常具有
ErrorNumber
属性。

错误号 208 读取(来源):

对象名称“%.*ls”无效。


2
投票

我认为下面的代码更容易理解。

using(YourDbEntities db = new YourDbEntities()) 
{
  bool IsExists = db.Database
   .SqlQuery <int?> (@"
    SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_NAME = '" + yourTableName + "'
    ")
    .FirstOrDefault() > 0;

    return IsExists;
}

2
投票

在 EF Core 中,我添加了 TableExists 方法作为 DbContext 类的扩展方法。这是我使用 Dapper 的解决方案。

using System.Linq;
using Dapper;
using Microsoft.EntityFrameworkCore;

public static class DbContextsExtensions
{
    public static bool TableExists(this DbContext dbContext, string tableName)
    {
        var sqlQ = $"SELECT COUNT(*) as Count FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '{tableName}'";

        var conn = dbContext.Database.GetDbConnection();
        {
            if (conn != null)
            {
                // Query - method extension provided by Dapper library
                var count = conn.Query<int>(sqlQ).FirstOrDefault();

                return (count > 0);                    
            }
        }
        return false;
    }
}

这是一个用法示例:

if(context != null && context.TableExists("AppSettings"))
{
   // do something;
}

希望这对其他人有帮助。


1
投票

这是在 EF Core 中执行此操作的扩展方法(无需 Dapper):

public static async Task<bool> TableExists(this DbContext context, string tableName)
{
    var connection = (SqlConnection)context.Database.GetDbConnection();
    if (connection.State != ConnectionState.Open)
    {
        await connection.OpenAsync();
    }

    await using var command = connection.CreateCommand();
    command.CommandText = $"SELECT COUNT(*) FROM sys.tables WHERE name = '{tableName}'";
    var result = await command.ExecuteScalarAsync();
    var count = (int)result;
    return count > 0;
}

-2
投票

如果不存在,此代码会自动创建所有表

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            var x = modelBuilder.RegisterEntityType;
        }
© www.soinside.com 2019 - 2024. All rights reserved.