要处理的linq函数:两个字段相等或者为null或为空

时间:2012-10-24 08:18:25

标签: c# linq entity-framework

您好我有一个linq查询,我将一个对象与我数据库中存储的所有其他实体进行比较。名字和姓氏是必填字段,所以我不必检查是否为空。但在街道的情况下,我必须做这些检查。

如果两个字段都为空或空字符串或者它们是相同的,我想匹配。以下linq查询工作正常。

但是我在徘徊是没有办法让它更具可读性。例如,使用自定义函数,例如 Bool FieldsAreEqualOrBothNullOrEmpty(r.street,request.street)

无法想象如何做到这一点以及是否可能。

var same = 
   from r in db.Requests
   where r.firstName.ToLower() == request.firstName.ToLower()
      && r.lastName.ToLower() == request.lastName.ToLower()

      //Seems long to just compare two fields
      && ( string.IsNullOrEmpty(r.street) && string.IsNullOrEmpty(request.street) ) 
         || r.street.ToLower() == request.street.ToLower()

      select r;
return same;

3 个答案:

答案 0 :(得分:2)

我会简化:

var same = 
   from r in db.Requests
   where r.firstName.ToLower() == request.firstName.ToLower()
      && r.lastName.ToLower() == request.lastName.ToLower()
   select r;

if(string.IsNullOrEmpty(request.street)) {
    same = same.Where(r => string.IsNullOrEmpty(r.street));
} else {
    string street = request.street.ToLower();
    same = same.Where(r => r.street.ToLower() == street);
}

关于这一点的好处是它在每种情况下都使查询保持简单。 如果您选择,可以对前两个使用类似的逻辑,并且可以也可以移动到基于表达式的实用程序方法。未测试的:

public static IQueryable<T> FieldsAreEqualOrBothNullOrEmpty<T>(
    this IQueryable<T> source,
    Expression<Func<T, string>> member, string value)
{
    Expression body;
    if (string.IsNullOrEmpty(value))
    {
        body = Expression.Call(
            typeof(string), "IsNullOrEmpty", null, member.Body);
    }
    else
    {
        body = Expression.Equal(
            Expression.Call(member.Body, "ToLower", null),
            Expression.Constant(value.ToLower(), typeof(string)));
    }

    return source.Where(Expression.Lambda<Func<T,bool>>(
        body, member.Parameters));
}

然后:

var same = db.Requests
           .FieldsAreEqualOrBothNullOrEmpty(x => x.firstName, request.firstName)
           .FieldsAreEqualOrBothNullOrEmpty(x => x.lastName, request.lastName)
           .FieldsAreEqualOrBothNullOrEmpty(x => x.street, request.street);

答案 1 :(得分:1)

您可以使用适当的String.Equals来调用StringComparison但忽略大小写。

string.equals(r.street, request.street, StringComparison.OrdinalIgnoreCase);

为了进行比较,将字符串转换为小写是不好的做法,因为它不能在所有语言中可靠地工作,并且比使用忽略大小写的比较慢。例如,参见this answer

答案 2 :(得分:1)

如何在字符串IsEqualOrBothNullOrEmpty上创建扩展方法 -

public static class Extensions
{
   public static bool IsEqualOrBothNullOrEmpty(this string firstValue,
                           string secondValue)
   {
      return string.IsNullOrEmpty(firstValue) &&
               string.IsNullOrEmpty(secondValue)
                  || firstValue.ToLower() == secondValue.ToLower();
    }
}

并在您的查询中使用 -

var same = 
   from r in db.Requests
   where r.firstName.ToLower() == request.firstName.ToLower()
      && r.lastName.ToLower() == request.lastName.ToLower()
      && r.street.IsEqualOrBothNullOrEmpty(request.Street)

      select r;
return same;