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

发布于 2024-11-09 05:54:54 字数 151 浏览 0 评论 0原文

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

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

感谢您的任何帮助。

I'm using the Entity Framework with Code First approach. The base class DbContext has functions to create and delete the database as well as to check for its existence.

I want to check if a special table (entity) is existing or not. Is it possible with an framework implementation or do I need to write custom methods? If I need to write my own implementation, what would be the most generic approach to do that?

Thanks for any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

若言繁花未落 2024-11-16 05:54:54

如果您需要检查表是否存在,则必须调用自定义 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;

If you need to check existence of the table you must call custom SQL code:

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;

Table name is defined by default as the name of DbSet exposed on your derived context but the default name can be overriden either by fluent API's ToTable method or Table data annotation.

Doing this in the generic way is not something supposed in code first approach. That will require browsing metadata and manually explore to which table is the entity mapped - this can be pretty complex because entity can be mapped to multiple tables. Code first doesn't offer access to metadata. You must convert DbContext to ObjectContext and browse MetadataWorkspace.

Edit:

To convert DbContext to ObjectContext use this:

ObjectContext objContext = ((IObjectContextAdapter)dbContext).ObjectContext;
暮色兮凉城 2024-11-16 05:54:54

我无法对上一篇文章添加评论。我正在使用 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;
        }
    }

I can't add comment to previous post. I'm using SQL Compact and I don't know schema of the table. I'm using this code to check for table It's pretty the same that in previous post but It works for any table.

    /// <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;
        }
    }
沫尐诺 2024-11-16 05:54:54

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

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

An alternative method; it's not as efficient as Ladislav's, but it's not tied to SQL Server (edited to add Where clause to address performance issue):

bool CheckTableExists()
{
    try
    {
        context.YourTable.Where(s => s.<yourKeyField> = <impossible value>).Count();
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}
还在原地等你 2024-11-16 05:54:54

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

希望这对其他人有帮助。

In EF Core, I have added the TableExists method as a extension method for the DbContext class. Here is my solution using 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;
    }
}

And here is an usage example:

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

Hope this help other people.

风吹过旳痕迹 2024-11-16 05:54:54

假设:SQL Server

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

查询表不存在的 DbSet 将引发 EntityCommandExecutionException 以及类型为 SqlException 的内部异常。该内部异常有一个 ErrorNumber 属性。

错误号 208 读取(来源):

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

Assumption: SQL Server

Catching any old exception when querying the DbSet does not mean the table does not exist.

Querying a DbSet where the table does not exist will throw an EntityCommandExecutionException with an inner exception of type SqlException. That inner exception has an ErrorNumber property.

Error number 208 reads (source):

Invalid object name '%.*ls'.

独自唱情﹋歌 2024-11-16 05:54:54

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

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

I think following code is a little bit more understandable.

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;
}
若沐 2024-11-16 05:54:54

以下是在 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;
}

Here's an extension method for doing this in EF Core (without 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 = 
quot;SELECT COUNT(*) FROM sys.tables WHERE name = '{tableName}'";
    var result = await command.ExecuteScalarAsync();
    var count = (int)result;
    return count > 0;
}
三寸金莲 2024-11-16 05:54:54

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

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            var x = modelBuilder.RegisterEntityType;
        }

this code create all tables automatic if dose not exist

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            var x = modelBuilder.RegisterEntityType;
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文