У меня проблема с запросом, сгенерированным Entity Framework 6
Мы используем модель TPT (таблица на тип), у нас есть вложенное наследование 3-го уровня, и похоже, что EF6 теряется при запросе 3-го уровня.
Еще одной важной деталью является то, что мы реализовали «мягкое удаление», и у дочерних объектов есть столбец, сообщающий IS_ACTIVE, какая запись активна или нет.
У нас есть что-то вроде this в базе данных
Наши классы:
public abstract class Developer
{
public int Id { get; set; }
public string Name { get; set;}
public bool IsActive { get;set; }
...
}
public class FrontEnd : Developer
{
...
}
public class BackEnd : Developer
{
...
}
public abstract class FullStack : Developer
{
public int Level { get; set; }
}
public class Desktop : FullStack
{
...
}
public class Web : FullStack
{
...
}
Класс нашей карты в Entity Framework:
DeveloperMap.cs
public class DeveloperMap : EntityTypeConfiguration<Developer>
{
public DeveloperMap()
{
HasKey(x => x.Id);
Property(x => x.Id).HasColumnName("ID").HasColumnType("int")
.HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
Property(x => x.Name).HasColumnName("Name");
// Other Properties Here...
// This is the domain property used to indicate if a record is "deleted" or not
Ignore(x => x.IsActive);
ToTable("DEVELOPER");
}
}
FrontEndMap.cs
public class FrontEndMap : EntityTypeConfiguration<FrontEnd>
{
public FrontEndMap()
{
Map(x => x.Requires("IS_ACTIVE").HasValue(true);
// Other Properties Here...
ToTable("FRONTEND");
}
}
BackEndMap.cs
public class BackEndMap : EntityTypeConfiguration<BackEnd>
{
public BackEndMap()
{
Map(x => x.Requires("IS_ACTIVE").HasValue(true);
// Other Properties Here...
ToTable("BACKEND");
}
}
FullStackMap.cs
public class FullStackMap : EntityTypeConfiguration<FullStack>
{
public FullStackMap()
{
Property(x => x.Level).HasColumnName("LEVEL");
// Other Properties Here...
ToTable("FULLSTACK");
}
}
DesktopMap.cs
public class DesktopMap : EntityTypeConfiguration<Desktop>
{
public DesktopMap()
{
Map(x => x.Requires("IS_ACTIVE").HasValue(true);
// Other Properties Here...
ToTable("DESKTOP");
}
}
WebMap.cs
public class WebMap : EntityTypeConfiguration<Web>
{
public WebMap()
{
Map(x => x.Requires("IS_ACTIVE").HasValue(true);
// Other Properties Here...
ToTable("WEB");
}
}
Наш DbContext
DevContext.cs
public class DevContext : DbContext, IDisposable
{
public DevContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection)
{
Configuration.ValidateOnSaveEnabled = false;
Database.SetInitializer<DevContext>(null);
}
// AccessControl
public DbSet<Developer> Developers { get; set; }
}
Когда мы пытаемся загрузить данные из БД для заполнения сетки, используя
_context.Developers
У меня две проблемы:
Если один элемент DESKTOP или WEB имеет значение IS_ACTIVE = 0 в
база данных, EF6 не сбрасывает его.
EF6 создает запрос, который получает неверный тип таблицы. Мы
есть запись, которая должна быть загружена как DESKTOP, и когда я проверяю ее
мой код, я получаю сущность BACKEND!
Запрос, сгенерированный EF6, похож на
SELECT
"UnionAll2"."C1" AS "C1",
CASE WHEN (("Project6"."C1" = 1) AND ("Project6"."C1" IS NOT NULL)) THEN '0X0X0X' WHEN (("Project5"."C1" = 1) AND ("Project5"."C1" IS NOT NULL)) THEN '0X0X1X' WHEN ("UnionAll2"."C3" = 1) THEN '0X1X' ELSE '0X2X' END AS "C2",
-- get properties here like "Extent4"."PROPERTY" AS "PROPERTY"
CASE WHEN (("Project6"."C1" = 1) AND ("Project6"."C1" IS NOT NULL)) THEN "UnionAll2"."C2" WHEN (("Project5"."C1" = 1) AND ("Project5"."C1" IS NOT NULL)) THEN "UnionAll2"."C2" WHEN ("UnionAll2"."C3" = 1) THEN NULL END AS "C3",
-- get another properties here
CASE WHEN (("Project6"."C1" = 1) AND ("Project6"."C1" IS NOT NULL)) THEN NULL WHEN (("Project5"."C1" = 1) AND ("Project5"."C1" IS NOT NULL)) THEN NULL WHEN ("UnionAll2"."C3" = 1) THEN NULL ELSE "UnionAll2"."C4" END AS "C7"
FROM (SELECT
"UnionAll1"."ID" AS "C1",
"UnionAll1"."LEVEL" AS "C2",
"UnionAll1"."C1" AS "C3",
"UnionAll1"."C2" AS "C4"
FROM (SELECT
"Extent1"."ID" AS "ID",
"Extent1"."LEVEL" AS "LEVEL",
0 AS "C1",
NULL AS "C2"
FROM "SCHEMA"."FULLSTACK" "Extent1"
UNION ALL
SELECT
"Extent2"."ID" AS "ID",
NULL AS "C1",
0 AS "C2",
FROM "SCHEMA"."BACKEND" "Extent2"
WHERE ("Extent2"."MORE_IN_ATIVO" = 1)) "UnionAll1"
UNION ALL
SELECT
"Extent3"."ID" AS "ID",
NULL AS "C1",
1 AS "C2",
NULL AS "C3"
FROM "SCHEMA"."FRONTEND" "Extent3"
WHERE ("Extent3"."MOR2_IN_ATIVO" = 1)) "UnionAll2"
INNER JOIN "SCHEMA"."DEVELOPER" "Extent4" ON "UnionAll2"."C1" = "Extent4"."ID"
LEFT OUTER JOIN (SELECT
"Extent5"."ID" AS "ID",
-- get properties from DESKTOP here
1 AS "C1"
FROM "SCHEMA"."DESKTOP" "Extent5"
WHERE ("Extent5"."IS_ACTIVE" = 1) ) "Project5" ON "UnionAll2"."C1" = "Project5"."ID"
LEFT OUTER JOIN (SELECT
-- get properties from WEB here
"Extent6"."ID" AS "ID",
1 AS "C1"
FROM "SCHEMA"."WEB" "Extent6"
WHERE ("Extent6"."IS_ACTIVE" = 1) ) "Project6" ON "UnionAll2"."C1" = "Project6"."ID"
Раньше отлично работал на EF5. Что может быть не так?