c# - Entity Framework 和 Firebird DB 方言 1 - 不生成兼容的 sql

标签 c# entity-framework entity-framework-6 firebird firebird2.5

我正在尝试在 Firebird DB 之上使用 EF 设置一个项目,但它正在生成 Firebird 数据库拒绝的额外引号。

数据库已存在,并且该查询有匹配的记录。 错误是 FbException:动态 SQL 错误 SQL 错误代码 = -104 token 未知 - 第 2 行,第 4 列 .

但是,如果我删除它在 sql 中生成的引号,查询就会运行。

示例

using (var context = new ContextManager())
{
     var accounts = context.Accounts.Where(x => x.OBJID == 1).ToList();
}

生成sql

SELECT 
"A"."OBJID" AS "OBJID"
FROM "ACCOUNT" AS "A"

配置文件

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <entityFramework>
    <defaultConnectionFactory type="FirebirdSql.Data.EntityFramework6.FbConnectionFactory, EntityFramework.Firebird" />
    <providers>
      <provider invariantName="FirebirdSql.Data.FirebirdClient" type="FirebirdSql.Data.EntityFramework6.FbProviderServices, EntityFramework.Firebird" />
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="FirebirdSql.Data.FirebirdClient" publicKeyToken="3750abcc3150b00c" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

<system.data>
        <DbProviderFactories>
            <remove invariant="FirebirdSql.Data.FirebirdClient" />
            <add name="FirebirdClient Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description=".NET Framework Data Provider for Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient" />
        </DbProviderFactories>
    </system.data></configuration>

上下文类

public class ContextManager : DbContext
    {
        public ContextManager() : base(new FbConnection("database=xxxx.fdb;DataSource=localhost;user=xxx;password=xxxxx"),true)
        {

        }

        public ContextManager(string connString) : base(new FbConnection(connString), true)
        {
            //this.Configuration.LazyLoadingEnabled = false;
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }

        public DbSet<Account> Accounts { get; set; }
    }

账户模型

[Table("ACCOUNT")]
    public class Account
        {
            [Key]
            public int OBJID { get; set; }
        }

更新 - 检查并看到方言 1 已设置,因此我更新了查询字符串来表示它,查询没有更改,但错误发生了 FbException:动态 SQL 错误 SQL 错误代码 = -104 token 未知 - 第 2 行,第 4 列 .

enter image description here

最佳答案

问题在于您的数据库是方言 1,并且 Entity Framework 正在引用对象名称。不幸的是,方言 1 不支持带引号的对象名称,而是将其解释为字符串。这会导致 token 未知错误,因为解析器不需要字符串,而是对象名称。

我已经有一段时间没有对 Entity Framework 做过任何事情了(我通常用 Java 编程),我不确定是否有一个禁用引用的选项。

根据 Firebird bug 跟踪器中的此票证,Firebird Entity Framework 支持现在和将来都不会支持方言 1:DNET-580 .

因此,除非您将数据库升级到方言 3,否则您将无法使用 Entity Framework 。请注意,从方言 1 升级到方言 3 可能并不简单,特别是如果您的应用程序依赖于方言 1 特定语法(例如字符串的双引号)或行为(整数的浮点除法)。

解决方法

一个可能的解决方法是显式指定您的连接方言为方言 3(Firebird ADO.net 提供程序的连接属性 Dialect=3)。这将允许您使用方言 3 语法查询数据库。请注意,行为上可能存在一些差异,因为方言 3 有许多不同的规则。

不过我有点惊讶,因为我测试了 Firebird ADO.net 提供程序的许多最新版本,除非明确设置为 1,否则它默认为方言 3,所以这根本不应该是问题。

方言 3 的类似问题

这部分答案假设使用方言 3 数据库,其中表实际上称为 ACCOUNTS,而不是 Accounts。这不会导致 token 未知,但会导致表未知错误。

在这种情况下,问题在于默认配置从对象派生名称,并且它会引用名称。方言 3 中带引号的名称区分大小写(未带引号的名称不区分大小写,但以大写形式存储(和比较))。

您可以做的是通过注释您的对象来覆盖表名称:

[Table("ACCOUNTS")]
public class Account
{
    [Key]
    public int OBJID { get; set; }
}

您可以使用的另一个选项是 Fluent API,但我自己从未使用过它,所以我不完全确定您需要在哪里指定它(我认为在您的 DbContext 中)。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  //Changing Database table name to Metadata
  modelBuilder.Entity<Account>()
      .ToTable("ACCOUNTS");
}

可能还有其他选项可以影响命名约定。

另请参阅Entity Framework Code First - Changing a Table Name

关于c# - Entity Framework 和 Firebird DB 方言 1 - 不生成兼容的 sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49540768/

相关文章:

c# - Entity Framework - 同一实体的不同代理对象。并包括具有多条路径到同一目的地的行为

c# - 使用 transactionscope 时停止事务升级为分布式的推荐做法

c# - 在 .Net 应用程序中以集中或干净的方式检查所有操作的基于角色的权限

c# - 将一个服务注入(inject)另一个服务

c# - 如何将图片保存到数据库中?

c# - 使用通用列名将 where 子句添加到 linq 查询

mysql - EF6 for MySql InvalidOperationException

java - Hibernate fetchtype 是否默认加载目标对象(表)?

c# - 使用 Entity Framework 返回所有相关实体

entity-framework - 将 EF 4 EDMX 升级到 EF 6