如何跨实体框架查询共享对象级逻辑?

时间:2018-06-12 22:39:31

标签: c# entity-framework linq entity-framework-6 linq-to-entities

我希望在Entity Framework中的多个查询之间共享一些非常简单的逻辑。说我有以下型号

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; }
}

如果我使用普通LINQ,我可以创建一个简单的扩展方法,以便我确定该角色当前是否处于活动状态。

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

我可以这样使用它。

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

使用实体框架时,这会因为可怕而失败:

  

LINQ to Entities无法识别方法Boolean IsActive(Domain.Interfaces.IDateRestricted)方法,并且此方法无法转换为商店表达式。

有没有办法让我可以分享这个逻辑并让LINQ to Entities在查询时支持它?

1 个答案:

答案 0 :(得分:1)

您应该使用Expression<Func<IDateRestricted, bool>>代替Func<IDateRestricted, bool> - 提供的例外说明正好指向它:

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()));