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

嗨,我有一个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; 

我会简化:

 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 FieldsAreEqualOrBothNullOrEmpty( this IQueryable source, Expression> 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>( 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); 

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

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

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

如何在字符串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;