Некоторые фоны, которые я использую:
- Платформа сущностей 6.1
- Devart.Data.PostgreSql 7.11.1229
- Devart.Data 5.0.2021
- Postgresql 9.2
Из-за некоторого абстрактного ОО-моделирования 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 действительно выполнять неявный CAST изсимвол меняется от jsonb для соответствия типам?
Или, может быть, кто-то другой, отличная идея, либо с точки зрения 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"
Заранее спасибо.