Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query: LINQ Expression where fails when mapping to object with inherited properties #18421

Closed
jenscski opened this issue Oct 17, 2019 · 3 comments

Comments

@jenscski
Copy link

When writing dynamic linq queries with expressions, mapping to objects with inherited properties, an exception is thrown,

The code below gives

Unhandled exception. System.InvalidOperationException: The LINQ expression 'Where<MyTable>(
    source: DbSet<MyTable>,
    predicate: (m) => new MyTableDto{
        Id = m.Id,
        Deleted = m.Deleted,
        Name = m.Name
    }
    .Deleted == False)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Steps to reproduce

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace EFCoreSelectLinqBug
{
    class Program
    {
        static void Main(string[] args)
        {
            var factory = LoggerFactory.Create(configure =>
            {
                configure.SetMinimumLevel(LogLevel.Trace);
                configure.AddConsole();
            });

            var options = new DbContextOptionsBuilder<MyContext>()
                .UseLoggerFactory(factory)
                .UseSqlite("Datasource=:memory:");

            using (var db = new MyContext(options.Options))
            {
                ParameterExpression parameter = Expression.Parameter(typeof(MyTableDto), "x");
                MemberExpression property = Expression.Property(parameter, "Deleted");
                Expression<Func<MyTableDto, bool>> selector = Expression.Lambda<Func<MyTableDto, bool>>(property, parameter);

                var target = Expression.Constant(Convert.ToBoolean("false"));
                var method = Expression.Equal(selector.Body, target);

                Expression<Func<MyTableDto, bool>> lambda = Expression.Lambda<Func<MyTableDto, bool>>(method, selector.Parameters);

                var rows = db.MyTables
                    .Select(x => new MyTableDto
                    {
                        Id = x.Id,
                        Deleted = x.Deleted,
                        Name = x.Name,
                    })
                    .Where(lambda)
                    .ToList();
            }
        }
    }

    public class MyContext : DbContext
    {
        public MyContext(DbContextOptions<MyContext> options)
            : base(options)
        {
        }

        public DbSet<MyTable> MyTables { get; set; }
    }

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

        public bool Deleted { get; set; }

        public string Name { get; set; }
    }


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

        public bool Deleted { get; set; }
    }

    public class MyTableDto : MyTableIdentityDto
    {
        public string Name { get; set; }
    }
}

Further technical details

EF Core version: 3.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer and Sqlite
Target framework: .NET Core 3.0
Operating system: Windows 10

@jenscski
Copy link
Author

You may be correct. It did work in 2.2, but that was due to automatic local evaluation, so I may have to update my dtos then ...

@jenscski
Copy link
Author

But for clearification, EF does construct complex types, if the .Where(lambda) is written as .Where(x => x.Deleted==false), it works.

So it's a bug, or by design, that EF does not map correctly when using linq expressions and complex types.

@smitpatel
Copy link
Contributor

Duplicate of #18386

Make sure you are using same MemberInfo as in your complex type to create member access. This is not bug in EF as correct expression tree (as generated by compiler) works. And your dynamically generated expression tree is inaccurate.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants