我正在使用LINQ to SQL作为.NET MVC应用程序。
在我的数据库中,我有一堆列中含有“Y”或“N”值的列。
我正在尝试编写一个通用方法,它将返回数据库中columnName == 'Y'
到目前为止我已经有了这个
public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName)
{
return from approved in db.Approved
where approved.GetType().GetProperties().Where(x => x.Name.Equals(columnName)).Equals("Y")
select approved;
}
但是这给了我这个错误
'System.Reflection.MemberInfo'的成员访问'System.String Name'在类型'System.Reflection.PropertyInfo []上不合法。
知道我可能会出错吗?
谢谢。
答案 0 :(得分:3)
public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName)
{
var param = Expression.Parameter(typeof(Approved), "x");
var predicate = Expression.Lambda<Func<Approved,bool>>(
Expression.Equal(
Expression.PropertyOrField(param, columnName),
Expression.Constant("Y")
), param);
return db.Approved.Where(predicate);
}
编辑;如果属性实际为char?
,即'Y'
而非"Y"
,则:
public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName)
{
var param = Expression.Parameter(typeof(Approved), "x");
Expression prop;
var predicate = Expression.Lambda<Func<Approved, bool>>(
Expression.Equal(
(prop = Expression.PropertyOrField(param, columnName)),
Expression.Constant(prop.Type == typeof(string) ?
(object)"Y" : (object)'Y', prop.Type)
), param);
return db.Approved.Where(predicate);
}
(现在应对所有string
,char
和char?
答案 1 :(得分:1)
出现问题的是您无法在LINQ查询中使用反射。
有多少列 - 它是一个固定的相对较小的数字?如果是这样,请使用switch语句在多个LINQ查询之间进行选择。这更清洁,更快。
如果它是大量列,或者它们是动态的,您可以构造一个动态SQL语句,但要小心检查可能的注入攻击。
答案 2 :(得分:1)
approved.GetType().GetProperties()
将返回PropertyInfo []对象。即使使用Where
过滤它仍然不是属性的值,它基本上是满足批评的属性集合,即使该集合只有一个成员。
要按名称获取特定属性,最好使用Type类的GetProperty()
方法,如下所示:
PropertyInfo pi = approved.GetType().GetProperty(columnName);
但是,你还没有完成。您仍然必须按属性的值过滤对象,这是通过在属性上使用GetValue()
方法完成的,如下所示:
bool isApproved = pi.GetValue(approved, null).Equals("Y");
或将所有内容放在您的上下文中:
return from approved in db.Approved
where approved.GetType().GetProperty(columnName)
.GetValue(approved, null).Equals("Y")
select approved;
答案 3 :(得分:0)
GetType()
返回Type
GetProperties()
返回PropertyInfo[]
Where(..)
返回IEnumerable<PropertyInfo>
所以你打电话
IEnumerable<PropertyInfo>.Equals(string)
这似乎是错误的。不是吗?
答案 4 :(得分:-2)
这是因为最后一个Equals方法在过滤的IQueryable集合上运行,而不是在属性值本身上运行。
请改为尝试:
return from approved in db.Approved
where approved.GetType().GetProperties().Where(x => x.Name.Equals(columnName) && (string)x.GetValue(db.Approved, null) == "Y")
select approved;