对继承的类使用ModelBuilder Query方法(EF核心2.1)

时间:2019-02-11 19:58:33

标签: inheritance stored-procedures asp.net-core entity-framework-core

在基类上使用dbContext Query方法存在一些问题,该方法提供了对另一个类的某些继承(仅用于继承属性,不适用于模型/数据库构建)

在回购服务中,我称呼类似:

IEnumerable<CoasterExtended> coasters = await _db.Query<CoasterExtended>()
            .FromSql(GetCoastersProcedure, pageNumberParam, pageSizeParam, orderByParam, sortParam, breweryIdParam, searchParam, coasterTypeParam)
            .ToListAsync();

GetCoastersProcedure是一个SQL过程,它返回CoasterExtended类的所有属性。此类不用于模型/ db构建。它只是sql程序结果的镜像。

在我的OnModelCreating方法中,我只有:

builder.Query<CoasterExtended>();

查询sql过程的结果工作正常,直到我决定使用此类进行继承:

public class CollectionItemExtended : CoasterExtended {
    // some additional properties
}

和OnModelCreating方法:

builder.Query<CollectionItemExtended>();

(CoasterExtended类型的)查询现在返回错误“'FromSql'操作的结果中没有所需的列'Discriminator'”。我知道区分符用于继承的类型,但是我使用这两个类来镜像单独的sql过程的结果(这些结果我只是映射到所需的应用程序模型类)

因此,我不想选择(和伪造)鉴别器……我只想将sql过程的结果映射到独立的类(我已经继承了,只是因为我不想复制下面的属性和映射器)。如何实现查询结果将忽略继承并仅返回描述的类型?

2 个答案:

答案 0 :(得分:1)

问题在于基类和派生类都注册为query types,因此EF Core认为它们实现了TPH数据库继承策略(类似于普通实体类型)。

如果只想共享公共属性,请使用未注册为实体或查询类型的基类。

以您的情况为例,将CoasterExtended类的名称更改为CoasterExtendedBase,并让CoasterExtendedCollectionItemExtended都继承自该类:

public class CoasterExtended : CoasterExtendedBase { }

public class CollectionItemExtended : CoasterExtendedBase
{
    // some additional properties
}

现在您可以将CoasterExtendedCollectionItemExtended注册为查询类型,一切都会按预期进行。

答案 1 :(得分:0)

Query实际上在这里是多余的。这归结为FromSQL的逻辑。换句话说,Query<Foo>.FromSQL实际上只是FromSQL<Foo>。简而言之,FromSQL仅适用于实体类型,即实际映射到数据库的类型。这就是为什么它假设使用Discriminator列进行关系继承。换句话说,这并不意味着要映射到随机的C#对象类型。

编辑

尽管上述说法是正确的,但并不全面。最好说DbSet<T>.FromSQL必须是实体类型。 EF Core 2.1添加了对“查询集”的支持,但是您必须在上下文中定义这样的查询集才能使用它:

public DbQuery<CollectionItemExtended> CollectionItemExtendeds { get; set; }

然后,您可以在其上使用FromSQL

_context.CollectionItemExtendeds.FromSQL(...);