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

时间:2016-11-25 13:08:31

标签: c# .net entity-framework entity-framework-core

我们需要以动态方式构建EF表达式。例如,创建测试模型:

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

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

创建一个linq查询:

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

正常使用表达式:

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

q.Where(ex1).ToList();

我们需要从任何类型创建表达式,并且我们总是有一个字符串名称属性,因此我们尝试以这种方式构造它:

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();

但我们收到了警告:

  

Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory [8]   LINQ表达式'(new TestCard(){Id = [card] .disp_CardID,Guid =   [card] .Guid} .Id == 1030)'无法翻译,将会   在当地评估。要配置此警告,请使用   DbContextOptionsBuilder.ConfigureWarnings API(事件ID   'RelationalEventId.QueryClientEvaluationWarning')。 ConfigureWarnings   可以在重写DbContext.OnConfiguring方法时使用   在应用程序服务提供程序上使用AddDbContext。

我们在探查器中检查了结果SQL并得到了以下结果: q.Where(EX1).ToList();

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

和q.Where(ex2).ToList();

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

如果我尝试为 not-inherited 属性构建过滤器(例如Guid),我的方式很有效!

EF Core版本:1.0.1

如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

哇,这听起来像另一个EF Core bug(也发生在v.1.1.0(发布)中)。

两个表达式之间的唯一区别是属性访问器表达式ReflectedTypeMember

您可以这样修复:

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

但有这样的要求很奇怪,我建议将问题报告给EF Core GitHub