如何使用Entity Framework处理可选表?

时间:2015-06-30 14:02:06

标签: c# sql-server entity-framework

我正在使用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是否在以后的版本中引入了更清洁的东西。

1 个答案:

答案 0 :(得分:1)

实体框架似乎并不支持这一点,因此我认为有两种可能的方法:

使用原始SQL

检查表是否存在
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
}

尝试运行EF查询,并处理生成的异常

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
}