简体   繁体   English

如何在EF Core表达式中使用继承的属性?

[英]How to use inherited properties in EF Core expressions?

We need construct expression for EF in dynamic way. 我们需要以动态方式构造EF的表达。 For example create test models: 例如,创建测试模型:

public class TestBase
{
    public int Id { get; set; }
}

public class TestCard : TestBase
{
    public Guid Guid { get; set; }
}

Create a linq query: 创建一个linq查询:

var q = from card in Context.hlt_disp_Card
        select new TestCard
        {
            Id = card.disp_CardID,
            Guid = card.Guid
        };

Normal using expressions: 正常使用表达式:

Expression<Func<TestCard, bool>> ex1 = card => card.Id == 1030;

q.Where(ex1).ToList();

We require create expression from any type and always we have a string name of property, thus we tried construct it in this way: 我们需要使用任何类型的create表达式,并且始终具有属性的字符串名称,因此我们尝试以这种方式构造它:

var e = Expression.Parameter(typeof(TestCard), "card");
Expression bin = Expression.Property(e, "Id");
bin = Expression.Equal(bin, Expression.Constant(1030));
var ex2 = Expression.Lambda<Func<TestCard, bool>>(bin, e);

q.Where(ex2).ToList();

But we got a warning: 但是我们得到了警告:

Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory[8] The LINQ expression '(new TestCard() {Id = [card].disp_CardID, Guid = [card].Guid}.Id == 1030)' could not be translated and will be evaluated locally. Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory [8] LINQ表达式'(new TestCard(){Id = [card] .disp_CardID,Guid = [card] .Guid} .Id == 1030)'无法翻译并且将在本地进行评估。 To configure this warning use the DbContextOptionsBuilder.ConfigureWarnings API (event id 'RelationalEventId.QueryClientEvaluationWarning'). 要配置此警告,请使用DbContextOptionsBuilder.ConfigureWarnings API(事件ID为'RelationalEventId.QueryClientEvaluationWarning')。 ConfigureWarnings can be used when overriding the DbContext.OnConfiguring method or using AddDbContext on the application service provider. 重写DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext时,可以使用ConfigureWarnings。

We checked resulting SQL in profiler and got this results: q.Where(ex1).ToList(); 我们在探查器中检查了生成的SQL并得到了以下结果:q.Where(ex1).ToList(); built to 建于

SELECT [card].[disp_CardID], [card].[Guid]
FROM [hlt_disp_Card] AS [card]
WHERE [card].[disp_CardID] = 1030

and q.Where(ex2).ToList(); 和q.Where(ex2).ToList(); built to 建于

SELECT [card].[disp_CardID], [card].[Guid]
FROM [hlt_disp_Card] AS [card]

And if I try construct filter for not-inherited property (eg Guid) my way works well! 如果我尝试为非继承属性(例如Guid)构造过滤器,我的方法会很好!

EF Core version: 1.0.1 EF核心版本:1.0.1

How to solve this problem? 如何解决这个问题呢?

Wow, this sounds like another EF Core bug (happens also in v.1.1.0 (release)). 哇,这听起来像是另一个EF Core错误(在v.1.1.0(发行版)中也会发生)。

The only difference between the two expressions is the ReflectedType of the property accessor expression Member . 两个表达式之间的唯一差别是ReflectedType属性访问表达的Member

You can fix it this way: 您可以通过以下方式解决它:

// ...
var p = e.Type.GetProperty("Id");
if (p.ReflectedType != p.DeclaringType)
    p = p.DeclaringType.GetProperty(p.Name);
Expression bin = Expression.MakeMemberAccess(e, p);
// ...

but it's weird to have such requirement, I would suggest reporting the issue to EF Core GitHub . 但是有这样的要求很奇怪,我建议将问题报告给EF Core GitHub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM