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

ICollection.Contains isn't working properly with Enums in the DbSet<>.Where #18970

Closed
RebelionTheGrey opened this issue Nov 18, 2019 · 4 comments · Fixed by #19315
Closed

ICollection.Contains isn't working properly with Enums in the DbSet<>.Where #18970

RebelionTheGrey opened this issue Nov 18, 2019 · 4 comments · Fixed by #19315
Assignees
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Milestone

Comments

@RebelionTheGrey
Copy link

RebelionTheGrey commented Nov 18, 2019

DbContext.DbSet.Where isn't work properly with ICollection<T>, where T is an Enum.

So, for example, the code like this always return emply ICollection<>:
var result = await context.Users.Where(e => e.WorkingRoles.Contains(sameRole)).ToListAsync();

but sameCollection in the code below isn't empty.

            var rolesCollection= await context.Users.Select(e => e.WorkingRoles).ToListAsync();
            var sameCollection = tst.Where(e => e.Contains(request.Role));

Part of code to reproduce

pubilc class User
{
    public Guid Id { get;set;}
    public ICollection<Roles> WorkingRoles { get; set; }
    public string Name { get; set;}
    public string Password { get; set; }
}
public enum Roles
{
    Customer = 1,
    Seller = 2
}

public class UserStoreDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public UserStoreDbContext(DbContextOptions<UserStoreDbContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder); 
        
        modelBuilder.Entity<User>().Property(f => f.WorkingRoles).HasConversion(new RolesToStringConveter());
    }
}

public class RolesToStringConveter : ValueConverter<ICollection<Roles>, string>
{
    public RolesToStringConveter() : base(v => string.Join(";", v.Select(f => f.ToString())),
                                 v => v.Length > 0 ? v.Split(new[] { ';' }).Select(f => (Roles)Enum.Parse(typeof(Roles), f)).ToList() : new List<Roles>())
        { }
}

Let's context be the scoped instance of UserStoreDbContext resolved by standard MS DI.

class TmpStorage
{
     public Guid Id { get; set; }
     public ICollection<Roles> Roles { get; set; }
 }

public ICollection<User> GetUsersByWorkingRole(Roles role)
{
     var resultUserCollection = await context.Users.Where(e => e.WorkingRoles.Contains(role)).ToListAsync();

     var tmpRolesCollectionsList = await context.Users.Select(e => new TmpStorage() { Roles = e.WorkingRoles, Id = e.Id }).ToListAsync();
     var usersId = tmpRolesCollectionsList .Where(e => e.Roles.Contains(role)).Select(f => f.Id).ToList();
     var anotherResultUserCollection = await context.Users.Where(e => usersId.Contains(e.Id)).ToListAsync();

     return resultUserCollection;
}

So, in this method resultUserCollection always empty, but anotherResultUserCollection not, it contains correct users which have asked role in their WorkingRoles collection.

Further technical details

EF Core version: 3.1.0-preview3.19554.8
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: 3.1.100-preview3-014645
Operating system: Windows Server 2016.
IDE: Microsoft Visual Studio Community 2019 Preview Version 16.4.0 Preview 5.0

@RebelionTheGrey RebelionTheGrey changed the title DbSet<WhereICollection.Contains isn't working properly with Enums. ICollection.Contains isn't working properly with Enums in the DbSet<>.Where Nov 18, 2019
@ajcvickers
Copy link
Contributor

Note for triage: repros on 3.1. SQL generated is:

      SELECT [u].[Id], [u].[Name], [u].[Password], [u].[WorkingRoles]
      FROM [Users] AS [u]
      WHERE CAST(1 AS bit) = CAST(0 AS bit)

/cc @maumar @smitpatel

@smitpatel
Copy link
Contributor

We cannot translate Contains over ICollection<Roles> which is mapped as string on database side using value converter.

@ajcvickers
Copy link
Contributor

@smitpatel So we should throw then, right?

@smitpatel
Copy link
Contributor

Yup. Somewhere I guess we saw different types and converted it to false.

@ajcvickers ajcvickers added this to the 5.0.0 milestone Nov 22, 2019
smitpatel added a commit that referenced this issue Dec 13, 2019
Based on how values are expanded into InExpression values cannot be anything other than SqlConstant/SqlParameter

Resolves #18970

Apply fix for #17342 for cosmos
Also enable Contains tests in Cosmos which were already working
@smitpatel smitpatel added closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. and removed easy-win labels Dec 13, 2019
smitpatel added a commit that referenced this issue Dec 13, 2019
Based on how values are expanded into InExpression values cannot be anything other than SqlConstant/SqlParameter

Resolves #18970

Apply fix for #17342 for cosmos
Also enable Contains tests in Cosmos which were already working
smitpatel added a commit that referenced this issue Dec 13, 2019
Based on how values are expanded into InExpression values cannot be anything other than SqlConstant/SqlParameter

Resolves #18970

Apply fix for #17342 for cosmos
Also enable Contains tests in Cosmos which were already working
smitpatel added a commit that referenced this issue Dec 16, 2019
Based on how values are expanded into InExpression values cannot be anything other than SqlConstant/SqlParameter

Resolves #18970

Apply fix for #17342 for cosmos
Also enable Contains tests in Cosmos which were already working
@ajcvickers ajcvickers modified the milestones: 5.0.0, 5.0.0-preview1 Mar 13, 2020
@ajcvickers ajcvickers modified the milestones: 5.0.0-preview1, 5.0.0 Nov 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants