2011-05-23 82 views
19

我使用的是Code First方法的实体框架。基类DbContext具有创建和删除数据库以及检查其存在的功能。实体框架 - 如何检查表是否存在?

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

感谢您的任何帮助。

回答

31

如果您需要检查表的存在,你必须调用自定义的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暴露在你的派生上下文中的名字,但默认名可以被覆盖定义通过流利的API的ToTable方法或Table数据注释。

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

编辑:

要转换到DbContext使用ObjectContext此:

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

如何将DbContext转换为ObjectContext?我发现了不同的方法来检查表的存在。你是否有任何区别a)SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA ='TheSchema'AND TABLE_NAME ='TheTable'))或b) SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo] 。[TableName]')AND键入(N'U')?你能解释优点还是缺点?我宁愿使用最标准的一致方式。 – 0xbadf00d 2011-05-23 18:25:20

+0

通常,所有这些SQL选择查询相同的信息 - 这是获得相同结果的不同方式。 – 2011-05-23 18:29:22

+0

键入(N'U')是什么意思?你的版本会忽略表格模式,对吗? – 0xbadf00d 2011-05-23 18:32:44

2

的另一种方法;它不像Ladislav那样高效,但它并不依赖于SQL Server:

bool CheckTableExists() 
{ 
    try 
    { 
     context.YourTable.Count(); 
     return true; 
    } 
    catch (Exception) 
    { 
     return false; 
    } 
} 
+0

这是非常不推荐的性能明智的... – petric 2016-09-21 12:59:52

4

我无法在以前的帖子中添加评论。我正在使用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; 
     } 
    } 
1

假设:SQL服务器

查询DbSet并不意味着表不存在时捕获的任何旧的例外。

查询DbSet,如果表不存在将会抛出一个EntityCommandExecutionException,其内部例外类型为SqlException。该内部异常具有ErrorNumber属性。

错误编号208读取(source):

无效的对象名称%1!'。