PostgreSQL 提供程序为包含和 Concat 的实体框架生成的错误查询



我正在使用EF连接到PostgreSQL。EF 是 5.0 版本,Npgsql 是 2.0.14.3 版本。

我要运行的查询是:

var list = new List<string> { "test" };
var res = from t in db.Test
    where !list.Contains(string.Concat(t.test1, "_", t.test2))
    select t;
res.ToList();

生成的查询如下所示:

SELECT "Extent1"."id" AS "id","Extent1"."test1" AS "test1","Extent1"."test2" AS "test2" FROM "public"."test" AS "Extent1" WHERE 'test'!="Extent1"."test1" || '_' || "Extent1"."test2"

当我运行它时,出现一个错误:argument of WHERE must be type boolean, not type text.

但是,当我将!=更改为=时,它可以工作。当我在 Postgres 中的串联字符串周围添加参数时,它也可以工作,但我无法更改 EF 生成的查询。

解决方法是我将第二个(虚拟)元素添加到列表中,因为这样 EF 会生成一个稍微不同的查询,但它不是一个优雅的解决方案......

这是 pgSQL 中的错误吗?或者也许在 EF 提供程序中?你能提出一个更好的解决方案吗?

更多信息

表脚本:

CREATE TABLE test
(
  test1 character varying(255),
  test2 character varying(255),
  id integer NOT NULL,
  CONSTRAINT "PK" PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);

表的类:

[Table("test", Schema = "public")]
public class Test
{
    [Key]
    public int id { get; set; }
    public string test1 { get; set; }
    public string test2 { get; set; }
}

应用配置:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
  <connectionStrings>
    <add name="local" connectionString="Server=localhost;Port=5432;Database=test;User Id=user;Password=password;" providerName="Npgsql" />
  </connectionStrings>
  <system.data>
    <DbProviderFactories>
      <add name="Npgsql Data Provider" invariant="Npgsql" description="Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql" />
    </DbProviderFactories>
  </system.data>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>
</configuration>

是的,这是 EF 提供程序 Npgsql 中的一个错误。

根据 http://www.postgresql.org/docs/9.3/static/sql-syntax-lexical.html#SQL-PRECEDENCE-TABLE 的说法,!=||属于(any other),这意味着它们具有相同的优先级。它们也被保留为关联,因此查询将被解析为

SELECT ... FROM "public"."test" AS "Extent1"
WHERE ((('test'!="Extent1"."test1") || '_') || "Extent1"."test2")

这是错误的。正确的解析是

SELECT ... FROM "public"."test" AS "Extent1"
WHERE ('test'!=(("Extent1"."test1" || '_') || "Extent1"."test2"))

=的优先级低于!=,因此可以正常工作。

此问题的修复程序包含在 https://github.com/npgsql/Npgsql/pull/256 的拉取请求中。

最新更新