简体   繁体   中英

How to use inherited properties in EF Core expressions?

We need construct expression for EF in dynamic way. 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:

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:

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. To configure this warning use the DbContextOptionsBuilder.ConfigureWarnings API (event id 'RelationalEventId.QueryClientEvaluationWarning'). ConfigureWarnings can be used when overriding the DbContext.OnConfiguring method or using AddDbContext on the application service provider.

We checked resulting SQL in profiler and got this results: 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(); 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!

EF Core version: 1.0.1

How to solve this problem?

Wow, this sounds like another EF Core bug (happens also in v.1.1.0 (release)).

The only difference between the two expressions is the ReflectedType of the property accessor expression 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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