【问题标题】:Using custom methods in linq to entities在 linq to 实体中使用自定义方法
【发布时间】:2015-05-26 07:40:58
【问题描述】:

我的数据库中有一个Person 表,其中包含NationalId 字段。 有没有办法使用Ef code firstLinq to entities 加载所有带有NationalId 的人员,而不将所有Persons 加载到内存中?

类似的东西:

public  bool IsEven(int number)
{
   return number % 2 == 0;
}

var context = new MyContext();
var personsWithEvenNationalId = context.Persons
                                       .Where(x=> IsEven(x.NationalId))
                                       .ToList();

【问题讨论】:

    标签: c# entity-framework ef-code-first linq-to-entities


    【解决方案1】:

    您必须进行内联检查

    var personsWithEvenNationalId = context.Persons
                                           .Where(x=> x.NationalId%2 == 0)
                                           .ToList();
    

    Linq to Entities 基本上不知道如何将您的自定义方法转换为 SQL。如果您确实需要使用自定义方法,则必须将 Persons 设为可枚举,然后使用您的自定义方法,即

    var personsWithEvenNationalId = context.Persons
                                           .AsEnumerable()
                                           .Where(x=> IsEven(x.NationalId))
                                           .ToList();
    

    但这并不理想,因为它会加载所有 Persons 然后过滤 IsEven

    编辑:考虑一下,如果您不想每次都内联编写它,您还可以为IQueryable<Person> 创建一个扩展方法。像这样你建立一个Expression

        public static IQueryable<Person> WhereEven(this IQueryable<Person> source, Expression<Func<Person, int>> property)
        {
            var expression = Expression.Equal(
                Expression.Modulo(
                    property.Body,
                    Expression.Constant(2)),
                Expression.Constant(0));
    
            var methodCallExpression = Expression.Call(typeof (Queryable),
                "where",
                new Type[] {source.ElementType},
                source.Expression,
                Expression.Lambda<Func<Person, bool>>(expression, property.Parameters));
    
            return source.Provider.CreateQuery<Person>(methodCallExpression);
        }
    

    并使用它:

    context.Persons.WhereEven(x => x.NationalId).ToList();
    

    【讨论】:

      【解决方案2】:

      您需要一个提供Expression 的函数(或属性或字段)来执行您想要的投影,而不是一个函数:

      public static Expression<Func<int, bool>> IsEven()
      {
          return number => number % 2 == 0;
      }
      

      你现在可以写了:

      using(var context = new MyContext())
      {
          var personsWithEvenNationalId = context.Persons
              .Select(x=> x.NationalId)
              .Where(IsEven())
              .ToList();
      }
      

      【讨论】:

      • 它有效,但是如果我想选择Person 的所有字段而不是只选择NationalId 怎么办?
      • 这太棒了!但是我请求你指导我把这些方法或道具放在哪里,你怎么称呼它们? PLEEEAAASEEEE
      猜你喜欢
      • 2011-03-25
      • 2015-06-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多