某些背景,我正在使用:
由于一些抽象的OO建模,EntityFramework被迫对不同的表执行一些联合,其中一些可能包含JSONB列,而其他则不包含。本质上,它看起来如下:
select
c1,
c2,
case when
c4 = true then c3
else cast(null as varchar)
end as c3,
c4
from (
select
id as c1,
name as c2,
attributes as c3,
true as c4
from
myjsonbtable
union all
select
id as c1,
name as c2,
null as c3,
false as c4
from
mynormaltable
) as union_all
运行此查询时,Postgresql将提供以下错误;
ERROR: CASE types character varying and jsonb cannot be matched
这是由于以下代码行导致的:
case when c4 = true then c3 else cast(null as varchar) end as c3
我们可以这样解决:
case when c4 = true then c3 else cast(null as jsonb) end as c3
假设我们用棍子打EF。如果我们可以告诉Postgresql如何转换这些类型,则更简单:
类似:
create cast (varchar as jsonb) with function to_jsonb(anyelement) as implicit;
但是我想知道,CASE是否真的能够执行从字符到jsonb的隐式CAST,以匹配类型?
或者从Postgresql或EntityFramework的角度来看,也许另一个人都是一个精妙的想法。
修改:查看提交的代码示例
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DevartExample
{
[Table("BaseClass")]
public class BaseClass
{
[Index]
public int Id { get; set; }
}
[Table("ClassWithJsonb")]
public class ClassWithJsonB : BaseClass
{
[Column(TypeName = "jsonb")]
public string Json { get; set; }
}
[Table("ClassWithoutJsonb")]
public class ClassWithoutJsonB : BaseClass
{
public int MyProperty { get; set; }
}
public class DevartDbProvider : DbContext
{
public IDbSet<BaseClass> BaseClass
{
get;
set;
}
public IDbSet<ClassWithJsonB> ClassWithJsonB
{
get;
set;
}
public IDbSet<ClassWithoutJsonB> ClassWithoutJsonB
{
get;
set;
}
public DevartDbProvider() : base("DevartExample")
{
Database.Log = s => { System.Diagnostics.Debug.WriteLine(s); };
}
}
class Program
{
static void Main(string[] args)
{
DevartDbProvider devartDbProvider = new DevartDbProvider();
devartDbProvider.BaseClass.FirstOrDefault();
}
}
}
输出此查询:
SELECT
"Limit1"."C1",
"Limit1"."Id",
"Limit1"."C2",
"Limit1"."C3"
FROM ( SELECT
"Extent1"."Id",
CASE WHEN ( NOT (("Project2"."C1" = true) AND ("Project2"."C1" IS NOT NULL))) AND ( NOT (("Project1"."C1" = true) AND ("Project1"."C1" IS NOT NULL))) THEN '0X' WHEN ("Project2"."C1" = true) AND ("Project2"."C1" IS NOT NULL) THEN '0X0X' ELSE '0X1X' END AS "C1",
CASE WHEN ( NOT (("Project2"."C1" = true) AND ("Project2"."C1" IS NOT NULL))) AND ( NOT (("Project1"."C1" = true) AND ("Project1"."C1" IS NOT NULL))) THEN CAST(NULL AS varchar) WHEN ("Project2"."C1" = true) AND ("Project2"."C1" IS NOT NULL) THEN "Project2"."Json" END AS "C2",
CASE WHEN ( NOT (("Project2"."C1" = true) AND ("Project2"."C1" IS NOT NULL))) AND ( NOT (("Project1"."C1" = true) AND ("Project1"."C1" IS NOT NULL))) THEN CAST(NULL AS int) WHEN ("Project2"."C1" = true) AND ("Project2"."C1" IS NOT NULL) THEN CAST(NULL AS int) ELSE "Project1"."MyProperty" END AS "C3"
FROM "BaseClass" AS "Extent1"
LEFT OUTER JOIN (SELECT
"Extent2"."Id",
"Extent2"."MyProperty",
true AS "C1"
FROM "ClassWithoutJsonb" AS "Extent2" ) AS "Project1" ON "Extent1"."Id" = "Project1"."Id"
LEFT OUTER JOIN (SELECT
"Extent3"."Id",
"Extent3"."Json",
true AS "C1"
FROM "ClassWithJsonb" AS "Extent3" ) AS "Project2" ON "Extent1"."Id" = "Project2"."Id"
LIMIT 1
) AS "Limit1"
谢谢。
答案 0 :(得分:0)
您正在使用流畅的映射(不是XML映射),不是吗?确保将相应属性的列类型设置为jsonb:.HasColumnType(“ jsonb”);
如果这样做没有帮助,请send us一个小型测试项目来重现问题。