实体框架核心LINQ类属性/方法不能使用包含的属性

时间:2017-11-24 11:48:32

标签: c# entity-framework linq entity-framework-core

我有一个User类,其中包含导航属性Settings和一个只读属性IsVisibleInApp

目前此代码有效:

var users = context.Users.Include(x => x.Settings)
   .Where(x => x.Settings.IsApproved && x.Settings.IsAvailable && x.UserType == 2);

但是我必须经常使用这些检查,所以我尝试使用一个属性,并在运行时将Settings变为null。

这是我的代码。

public bool IsVisibleInApp
{
  get
  {
    return this.Settings.IsApproved && this.Settings.IsAvailable && this.UserType == 2;
  }
}

...
...

void SomeMethod(){
    var users = context.Users.Include(x => x.Settings)
       .Where(x => x.IsVisibleInApp).ToList();

我可以看到外键this.SettingsID是有效值。我猜属性/方法不能在Where上的DBSets子句中使用,因为它们会被转换为SQL? 但肯定有一种解决方法......或者我必须首先执行.ToList()然后再使用.Where调用,但这意味着从数据库中提取所有行很多额外的工作......

1 个答案:

答案 0 :(得分:3)

你不能按照你想要的方式去做(EF不会进入你的属性getter并查看你在那里做的事情),但你可以通过将它包装在静态表达式中来减少代码重复:

public static Expression<Func<User, bool>> IsVisibleInAppExpression = x =>
    x.Settings.IsApproved && x.Settings.IsAvailable && x.UserType == 2;

然后像这样使用:

var users = context.Users.Include(x => x.Settings)
   .Where(User.IsVisibleInAppExpression).ToList();

或者通过创建扩展方法:

public static class Extensions {
    public static IQueryable<User> VisibleInAppOnly(this IQueryable<User> query) 
    {
         return query.Where(x => 
             x.Settings.IsApproved && x.Settings.IsAvailable && x.UserType == 2);
    }
}

使用这样:

var users = context.Users.Include(x => x.Settings).VisibleInAppOnly();