postgresql自定义强制转换以匹配不同的案例类型

时间:2018-10-18 11:22:24

标签: entity-framework-6 postgresql-9.2 jsonb devart

某些背景,我正在使用:

  • 实体框架6.1
  • Devart.Data.PostgreSql 7.11.1229
  • Devart.Data 5.0.2021
  • PostgreSQL 9.2

由于一些抽象的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"

谢谢。

1 个答案:

答案 0 :(得分:0)

您正在使用流畅的映射(不是XML映射),不是吗?确保将相应属性的列类型设置为jsonb:.HasColumnType(“ jsonb”);

如果这样做没有帮助,请send us一个小型测试项目来重现问题。