- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试根据用户提供的一组收集条件在 Entity Framework 中构建动态 LINQ 查询。最终,这将包括更复杂的行为,但目前我只有一个字段名称和值的列表,我想返回字段名称具有这些值的所有记录。
我的基本结构是这样的:
public IEnumerable<ThingViewModel> getMythings(SelectionCriteria selectionCriteria)
{
var predicate = constructPredicate<Thing>(selectionCriteria);
var things = this.dbContext.Things.Where(predicate).ToList();
return Mapper.Map<List<Thing>, List<ThingViewModel>>(things);
}
所有有趣的工作都在 constructPredicate() 中:
private static Expression<Func<T, bool>> constructPredicate<T>(SelectionCriteria selectionCriteria)
{
// using Pete Montgomery's PredicateBuilder:
// http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/
var predicate = PredicateBuilder.True<T>();
foreach (var item in selectionCriteria.andList)
{
// Accessing foreach values in closures can result in unexpected results.
// http://stackoverflow.com/questions/14907987/access-to-foreach-variable-in-closure
var fieldName = item.fieldName;
var fieldValue = item.fieldValue;
var parameter = Expression.Parameter(typeof (T), "t");
var property = Expression.Property(parameter, fieldName);
var value = Expression.Constant(fieldValue);
var lambda = buildCompareLambda<T>(property, value, parameter);
predicate = predicate.And(lambda);
}
return predicate;
}
所有这些看起来都是一个非常合理的结构,但我在 buildCompareLambda() 中遇到了困难。我没有看到以通用方式执行此操作的方法,我必须为不同的类型创建不同的方法。我从处理字符串开始,这很简单。接下来我尝试处理整数,但事实证明数据库中的整数字段可以为空,这引入了全新的复杂性。
到目前为止,我的 buildCompareLambda():
private static Expression<Func<T, bool>> buildCompareLambda<T>(
MemberExpression property,
ConstantExpression value,
ParameterExpression parameter)
{
Expression<Func<T, bool>> lambda = null;
if (property.Type == typeof (string))
lambda = buildStringCompareLambda<T>(property, value, parameter);
else if (property.Type.IsGenericType && Nullable.GetUnderlyingType(property.Type) != null)
lambda = buildNullableCompareLambda<T>(property, value, parameter);
if (lambda == null)
throw new Exception(String.Format("SelectrionCriteria cannot handle property type '{0}'", property.Type.Name));
return lambda;
}
正如我所说,buildStringCompareLambda 非常简单:
private static Expression<Func<T, bool>> buildStringCompareLambda<T>(
MemberExpression property,
ConstantExpression value,
ParameterExpression parameter)
{
var equalsMethod = typeof (string).GetMethod("Equals",
new[] {typeof (string), typeof (string)});
var comparison = Expression.Call(equalsMethod, property, value);
return Expression.Lambda<Func<T, bool>>(comparison, parameter);
}
但是 buildNullableCompareLambda() 变得丑陋了:
private static Expression<Func<T, bool>> buildNullableCompareLambda<T>(MemberExpression property,
ConstantExpression value,
ParameterExpression parameter)
{
var underlyingType = Nullable.GetUnderlyingType(property.Type);
if (underlyingType == typeof (int) || underlyingType == typeof (Int16) || underlyingType == typeof (Int32) ||
underlyingType == typeof (Int64) || underlyingType == typeof (UInt16) || underlyingType == typeof (UInt32) ||
underlyingType == typeof (UInt64))
{
var equalsMethod = underlyingType.GetMethod("Equals", new[] {underlyingType});
var left = Expression.Convert(property, underlyingType);
var right = Expression.Convert(value, underlyingType);
var comparison = Expression.Call(left, equalsMethod, new Expression[] {right});
return Expression.Lambda<Func<T, bool>>(comparison, parameter);
}
return null;
}
我打算在 buildNullableCompareLambda() 中添加对更多类型的支持,并将每种类型的处理移动到一个函数中,以便可以从 buildCompareLambda() 和 buildNullableCompareLambda() 调用相同的代码。但那是为了将来——目前我坚持比较整数。目前,我正在将属性和值都转换为基础类型,因为我不想为每个整数类型使用单独的函数,并且我不希望用户必须关心 EF 是否为字段建模转换为 Int16 或 Int32。这对非空字段有效。
我一直在浏览 SO,并找到了一些答案,这就是我所得到的,但我所看到的关于处理可空类型的答案都没有真正对我有用,因为它们不'真正处理空值。
在我的例子中,如果用户向我传递一个选择标准,其中一个项目应该等于 null,我想返回该字段为 null 的记录,而这一点是关于将双方都转换为基本类型似乎不起作用。我收到“对象引用未设置到对象的实例”异常。
在 SQL 中,我想要的是“WHERE field IS NULL”,如果值为 null,或者“WHERE field = 'value'”,如果不是。而且我不知道如何将这种替代方法构建到表达式树中。
有什么想法吗?
补充:有人建议我使用 Expression.Equal()。
这样,我的循环就变成了:
private static Expression<Func<T, bool>> constructPredicate<T>(SelectionCriteria selectionCriteria)
{
var predicate = PredicateBuilderEx.True<T>();
var foo = PredicateBuilder.True<T>();
foreach (var item in selectionCriteria.andList)
{
var fieldName = item.fieldName;
var fieldValue = item.fieldValue;
var parameter = Expression.Parameter(typeof (T), "t");
var property = Expression.Property(parameter, fieldName);
var value = Expression.Constant(fieldValue);
var comparison = Expression.Equal(property, value);
var lambda = Expression.Lambda<Func<T, bool>>(comparison, parameter);
predicate = PredicateBuilderEx.And(predicate, lambda);
}
return predicate;
}
那是行不通的。我得到一个异常(exception):
The binary operator Equal is not defined for the types 'System.Nullable`1[System.Int16]' and 'System.Int16'.
最佳答案
通常情况下,这里的人可能不会完全想出答案,但他们已经知道了大部分的方法,并且足够接近,我可以算出其余的。
Expression.Equal 要求两个参数的类型相同。如果一个可为空,则它们都需要为空。但这并不难处理:
private static Expression<Func<T, bool>> constructPredicate<T>(SelectionCriteria selectionCriteria)
{
var predicate = PredicateBuilderEx.True<T>();
var foo = PredicateBuilder.True<T>();
foreach (var item in selectionCriteria.andList)
{
var fieldName = item.fieldName;
var fieldValue = item.fieldValue;
var parameter = Expression.Parameter(typeof (T), "t");
var property = Expression.Property(parameter, fieldName);
var value = Expression.Constant(fieldValue);
var converted = Expression.Convert(value, property.Type);
var comparison = Expression.Equal(property, converted);
var lambda = Expression.Lambda<Func<T, bool>>(comparison, parameter);
predicate = PredicateBuilderEx.And(predicate, lambda);
}
return predicate;
}
谢谢大家。
关于c# - 表达式树中的可空比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23920450/
我已经为使用 JGroups 编写了简单的测试。有两个像这样的简单应用程序 import org.jgroups.*; import org.jgroups.conf.ConfiguratorFact
我有一个通过 ajax 检索的 json 编码数据集。我尝试检索的一些数据点将返回 null 或空。 但是,我不希望将那些 null 或空值显示给最终用户,或传递给其他函数。 我现在正在做的是检查
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Why does one often see “null != variable” instead of “
嗨在我们公司,他们遵循与空值进行比较的严格规则。当我编码 if(variable!=null) 在代码审查中,我收到了对此的评论,将其更改为 if(null!=variable)。上面的代码对性能有影
我正在尝试使用 native Cordova QR 扫描仪插件编译项目,但是我不断收到此错误。据我了解,这是代码编写方式的问题,它向构造函数发送了错误的值,或者根本就没有找到构造函数。那么我该如何解决
我在装有 Java 1.8 的 Windows 10 上使用 Apache Nutch 1.14。我已按照 https://wiki.apache.org/nutch/NutchTutorial 中提
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: what is “=null” and “ IS NULL” Is there any difference bet
Three-EyedRaven 内网渗透初期,我们都希望可以豪无遗漏的尽最大可能打开目标内网攻击面,故,设计该工具的初衷是解决某些工具内网探测速率慢、运行卡死、服务爆破误报率高以及socks流
我想在Scala中像在Java中那样做: public void recv(String from) { recv(from, null); } public void recv(String
我正在尝试从一组图像补丁中创建一个密码本。我已将图像(Caltech 101)分成20 X 20图像块。我想为每个补丁创建一个SIFT描述符。但是对于某些图像补丁,它不返回任何描述符/关键点。我尝试使
我在验证器类中自动连接的两个服务有问题。这些服务工作正常,因为在我的 Controller 中是自动连接的。我有一个 applicationContext.xml 文件和 MyApp-servlet.
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 已关闭10 年前。 问题必须表现出对要解决的问题的最低程度的了解。告诉我们您尝试过做什么,为什么不起作用,以
大家好,我正在对数据库进行正常的选择,但是 mysql_num_rowsis 为空,我不知道为什么,我有 7 行选择。 如果您发现问题,请告诉我。 真的谢谢。 代码如下: function get_b
我想以以下格式创建一个字符串:id[]=%@&stringdata[]=%@&id[]=%@&stringdata[]=%@&id[]=%@&stringdata[]=%@&等,在for循环中,我得到
我正在尝试使用以下代码将URL转换为字符串: NSURL *urlOfOpenedFile = _service.myURLRequest.URL; NSString *fileThatWasOpen
我正在尝试将NSNumber传递到正在工作的UInt32中。然后,我试图将UInt32填充到NSData对象中。但是,这在这里变得有些时髦... 当我尝试将NSData对象中的内容写成它返回的字符串(
我正在进行身份验证并收到空 cookie。我想存储这个 cookie,但服务器没有返回给我 cookie。但响应代码是 200 ok。 httpConn.setRequestProperty(
我认为 Button bTutorial1 = (Button) findViewById(R.layout.tutorial1); bTutorial1.setOnClickListener
我的 Controller 中有这样的东西: model.attribute("hiringManagerMap",hiringManagerMap); 我正在访问此 hiringManagerMap
我想知道如何以正确的方式清空列表。在 div 中有一个列表然后清空 div 或列表更好吗? 我知道这是一个蹩脚的问题,但请帮助我理解这个 empty() 函数:) 案例)如果我运行这个脚本会发生什么:
我是一名优秀的程序员,十分优秀!