How can I share object level logic across Entity Framework queries?

c# entity-framework entity-framework-6 linq linq-to-entities

Question

I am looking to share some very simple logic across multiple queries in Entity Framework. Say I have the following models

public class User
{
    // user properties
    public ICollection<UserRole> Roles { get; set; }
}

public class UserRole : IDateRestricted
{
    public RoleType Type { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
}

public interface IDateRestricted
{
    DateTime StartDate { get; set; }
    DateTime? EndDate { get; set; }
}

If I was using normal LINQ I could create a simple extension method that would allow me to determine if the role was currently active.

public static class DateRestrictedExtensions
{
    public static Boolean IsActive(this IDateRestricted entity)
    {
        return entity.StartDate <= DateTime.Now && (entity.EndDate == null || entity.EndDate > DateTime.Now);
    }
}

and I could use it like so.

var admins = users.Where(x => x.Roles.Any(role => role.Type == RoleType.Admin && role.IsActive()));

With entity framework this fails with the dreaded:

LINQ to Entities does not recognize the method Boolean IsActive(Domain.Interfaces.IDateRestricted) method, and this method cannot be translated into a store expression.

Is there a way that I can share this logic and have LINQ to Entities support it when querying?

1
0
6/13/2018 4:20:08 AM

Accepted Answer

You should use Expression<Func<IDateRestricted, bool>> instead of Func<IDateRestricted, bool> - presented exception's description exactly points to it:

public static class DateRestrictedExtensions
{
    public static Expression<Func<IDateRestricted, bool>> IsActive()
    {
        return entity => entity.StartDate <= DateTime.Now 
                         && (entity.EndDate == null || entity.EndDate > DateTime.Now);
    }
}

var admins = users.Where(x => x.Roles.AsQueryable().Where(role.Type == RoleType.Admin)
                                   .Any(DateRestrictedExtensions.IsActive()));
1
6/14/2018 10:30:35 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow