Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
360 views
in Technique[技术] by (71.8m points)

c# - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...