我正在使用Entity Framework 6来访问数据库。随着时间的推移,该数据库架构有几个略有不同的版本。当模式的某些部分可能缺少"可以这么说时,如何使用EF访问数据库。
例如,某个时候已将Tank
表添加到数据库中,因此我希望能够将其添加到我的上下文中:
public DbSet<Tank> Tanks { get; set; }
然后对它执行查询,如下所示:
var tanks = context.Tanks.Where( ... ).ToList()
但很明显,当针对没有此表的架构版本运行时会引发异常。
除了捕获异常并检查相应的SQL错误代码之外,有没有办法干净利落地处理这个问题?最好在运行查询之前获取EF以检查表是否存在的某种方式?我无法在DbContext
课程上看到任何可以提供帮助的内容,互联网搜索也没有发现任何内容。我想我可以下载到原始SQL来做它。
我应该指出,没有&#34;架构版本号&#34;或者有助于确定访问哪个版本数据库的任何表上的类似列。也许这本来是一个好主意(后见之明和所有这些),但它从未发生过,并且将这样的东西改装到现有装置将是困难的。
另外,在我的特定场景中,我只是从现有数据库中读取数据:我不需要使用EF写入数据库,我也不需要获取EF来构建模式对我来说。
编辑:我刚刚发现了这个问题:Entity Framework - How to check if table exists?,但答案基本上建议执行SQL查询。那是从2011年开始,我想知道EF是否在以后的版本中引入了更清洁的东西。
答案 0 :(得分:1)
实体框架似乎并不支持这一点,因此我认为有两种可能的方法:
public static class DbContextExtensions
{
public static bool HasTableNamed(
this DbContext context, string table, string inSchema = "dbo")
{
string sql = @"SELECT CASE WHEN EXISTS
(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA=@p0 AND TABLE_NAME=@p1) THEN 1 ELSE 0 END";
return context.Database.SqlQuery<int>(sql, inSchema, table).Single() == 1;
}
}
像这样使用:
MyContext db = ... // class derived from DbContext
...
if (db.HasTableNamed("MyOptionalTable"))
{
// the table exists in the database
}
else
{
// the table DOES NOT exist in the database
}
public static class EntityCommandExecutionExceptionExtensions
{
public static bool IsInvalidObjectNameError(
this EntityCommandExecutionException exception)
{
const int InvalidObjectName = 208;
var sqlException = exception.InnerException as SqlException;
if (sqlException == null)
{
return false;
}
return sqlException.Errors.Cast<SqlError>().Any(
error => error.Number == InvalidObjectName);
}
}
像这样使用:
try
{
// run some EF query
}
catch (EntityCommandExecutionException exception)
{
if (!exception.IsInvalidObjectNameError())
{
throw;
}
// one of the objects referenced by the query is missing
}