实体框架-如何检查表是否存在
本文关键字:检查表 是否 存在 框架 实体 | 更新日期: 2023-09-27 17:57:32
我使用的是带有代码优先方法的实体框架。基类DbContext具有创建和删除数据库以及检查其存在性的函数。
我想检查一个特殊的表(实体)是否存在。框架实现可能吗?或者我需要编写自定义方法吗?如果我需要编写自己的实现,那么最通用的方法是什么?
谢谢你的帮助。
如果需要检查表的存在性,则必须调用自定义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;
我无法在上一篇文章中添加评论。我使用的是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;
}
}
一种替代方法;它不如Ladislav的高效,但它与SQL Server无关(经过编辑,添加了Where子句来解决性能问题):
bool CheckTableExists()
{
try
{
context.YourTable.Where(s => s.<yourKeyField> = <impossible value>).Count();
return true;
}
catch (Exception)
{
return false;
}
}
假设:SQL Server
查询DbSet
时捕获任何旧异常并不意味着表不存在。
查询一个不存在表的DbSet
将抛出一个具有类型为SqlException
的内部异常的EntityCommandExecutionException
。该内部异常具有ErrorNumber
属性。
错误编号208读取(来源):
对象名'%1!'无效。
我认为下面的代码更容易理解。
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;
}
在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;
}
希望这能帮助其他人。
这里有一个在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;
}
如果剂量不存在,此代码将自动创建所有表
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var x = modelBuilder.RegisterEntityType;
}