koenbeuk / EntityFrameworkCore.Projectables

Project over properties and functions in your linq queries
MIT License
289 stars 20 forks source link

Not working with IQueryable.Contains #112

Open phuc1640 opened 1 month ago

phuc1640 commented 1 month ago

Let say we have a DbSet that have model like so

public class User {
  public int Id { get; set; }
  public int UserName { get; set; }
  public DateTimeOffset? SendMoneyAt { get; set; }
  [Projectable]
  public bool IsBacker => SendMoneyAt != null;
}

When we try a query like

var backerUsers = DbSet<User >().Where(u => u.IsBacker);

var usersWithLetterA = DbSet<User >().Where(u => u.UserName.Contains("A")).Select(u => u.Id);

var backerUsersWithLetterA = users.Where(u => usersWithLetterA.Contains(u.Id));

The query of backerUsersWithLetterA cannot be translated.

Is this a bug or a some limitation?

koenbeuk commented 3 weeks ago

I'm unable to reproduce this:

SELECT [u].[Id], [u].[SendMoneyAt], [u].[UserName]
FROM [User] AS [u]
WHERE [u].[Id] IN (
    SELECT [u0].[Id]
    FROM [User] AS [u0]
    WHERE [u0].[UserName] LIKE N'%A%'
)

test case:

        public class User
        {
            public int Id { get; set; }
            public string? UserName { get; set; }
            public DateTimeOffset? SendMoneyAt { get; set; }
            [Projectable]
            public bool IsBacker => SendMoneyAt != null;
        }

        [Fact]
        public void Issue112()
        {
            var dbContext = new SampleDbContext<User>();
            var usersWithLetterA = dbContext.Set<User>().Where(u => u.UserName!.Contains("A")).Select(u => u.Id);
            var backerUsersWithLetterA = dbContext.Set<User>().Where(u => usersWithLetterA.Contains(u.Id));

            Verifier.Verify(backerUsersWithLetterA.ToQueryString());
        }
samolesen commented 5 days ago

fyi, I hit the same error when calling Contains on a projectable property like this: myDbSet.Where(x => list.Contains(x.ProjectableProperty)).ToList();

Translation of member 'ProjectableProperty' on entity type 'MyType' failed. This commonly occurs when the specified member is unmapped.

@koenbeuk, I believe you carried a small bug in @phuc1640's example to the test case:

var dbContext = new SampleDbContext<User>();
var backerUsers = dbContext.Set<User>().Where(u => u.IsBacker); // missing in your test case
var usersWithLetterA = dbContext.Set<User>().Where(u => u.UserName!.Contains("A")).Select(u => u.Id);
var backerUsersWithLetterA = backerUsers.Where(u => usersWithLetterA.Contains(u.Id)); // I believe the intention was to refer to backerUsers instead of the User set

Verifier.Verify(backerUsersWithLetterA.ToQueryString());

That said I haven't executed this test myself, so I can't say whether it reproduces the error.