简体   繁体   English

如何使用实体框架处理可选表?

[英]How can I deal with optional tables using Entity Framework?

I'm using Entity Framework 6 to access a database.我正在使用 Entity Framework 6 来访问数据库。 There are several slightly different versions of this database's schema that have been deployed over time.随着时间的推移,该数据库的架构有几个略有不同的版本。 How can I access the database using EF when parts of the schema might be "missing", so to speak.可以这么说,当架构的某些部分可能“丢失”时,如何使用 EF 访问数据库。

For example, a Tank table was added to the database at some point, so I'd like to be able to add this to my context:例如,在某个时候将Tank表添加到数据库中,因此我希望能够将其添加到我的上下文中:

public DbSet<Tank> Tanks { get; set; }

and then perform queries against it, like so:然后对其执行查询,如下所示:

var tanks = context.Tanks.Where( ... ).ToList()

but obviously this throws an exception when running against versions of the schema that don't have this table.但显然这在针对没有该表的模式版本运行时会引发异常。

Is there any way of dealing with this cleanly, other than catching the exception and checking for the appropriate SQL error code?除了捕获异常并检查适当的 SQL 错误代码之外,还有什么方法可以干净地处理这个问题? Preferably some way of getting EF to check whether the table exists before I run the query?在我运行查询之前,最好采用某种方式让 EF 检查表是否存在? I couldn't see anything on the DbContext class that would help, and an internet search didn't really turn up anything either.我在DbContextDbContext不到任何DbContext东西,互联网搜索也没有真正找到任何东西。 I suppose I could drop down to raw SQL to do it.我想我可以下拉到原始 SQL 来做到这一点。


I should probably point out that there is no "schema version number" or similar column on any of the tables that would help to determine which version of the database is being accessed.我可能应该指出,任何表上都没有“模式版本号”或类似的列可以帮助确定正在访问哪个版本的数据库。 Maybe this would have been a good idea (hindsight and all that) but it never happened, and retrofitting something like this to existing installations would be difficult.也许这本来是一个好主意(事后诸葛亮),但它从未发生过,而且将这样的东西改造到现有装置中会很困难。

Also, in my particular scenario, I am only reading data from an existing database: I do not need to write to the database using EF, nor do I need to get EF to build the schema for me.此外,在我的特定场景中,我只从现有数据库读取数据:我不需要使用 EF 写入数据库,也不需要让 EF 为我构建架构。


EDIT : I just found this SO question: Entity Framework - How to check if table exists?编辑:我刚刚发现这个问题:实体框架 - 如何检查表是否存在? , but the answer basically recommended performing a SQL query. ,但答案基本上建议执行 SQL 查询。 That was from 2011 though, I'm wondering if EF has introduced anything cleaner in later versions.那是从 2011 年开始的,我想知道 EF 是否在以后的版本中引入了更清洁的东西。

The Entity Framework doesn't seem to support this, so as I see it there are two possible approaches:实体框架似乎不支持这一点,所以我认为有两种可能的方法:

Check whether the table exists using raw SQL使用原始 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;
    }
}

Used like so:像这样使用:

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
}

Attempt to run the EF query anyway, and handle the resulting exception无论如何都尝试运行 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);
    }
}

Used like so:像这样使用:

try
{
    // run some EF query
}
catch (EntityCommandExecutionException exception)
{
    if (!exception.IsInvalidObjectNameError())
    {
        throw;
    }

    // one of the objects referenced by the query is missing
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Entity Framework 6在运行时创建数据库和表? - How can I create a database and tables at runtime using Entity Framework 6? 如何使用实体框架在具有多个连接的查询中使用可选参数? - How can I use optional parameters in a query with multiple joins, using Entity Framework? 如何在 Entity Framework Core 中使用 Automapper 删除可选关系 - How can I remove an optional relationship using Automapper in Entity Framework Core 如何在ASP.NET MVC 5,Entity Framework 6中使用流畅的API映射表? - How can I map tables using fluent API in ASP.NET MVC 5, Entity Framework 6? 如何使用 Entity Framework C# 获取与特定表相关的表名 - How I can get the name of tables has relation with specific table using Entity Framework C# 如何使用 linq 和实体框架访问表中特定列的所有值? - How can I access all values from a specific column in tables using linq and Entity Framework? 如何让实体框架不为某些表创建类? - How can I make Entity Framework not create a class for some tables? 如何使用与Entity Framework一起使用表的存储过程 - How can I use a stored procedure that uses tables with Entity Framework 如何使用实体框架获取数据库表的数量? - How can I use entity framework to get a count of database tables? 如何通过Entity Framework验证表之间的所有关系? - how I can verify all the releations between tables by Entity Framework?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM