我正在创建一个自定义报告工具,允许用户输入标准列表。
public partial class CustomReportCriteria
{
public int Id { get; set; }
public int ReportId { get; set; }
public string Operator { get; set; }
public string CriteriaValue { get; set; }
public string CriteriaType { get; set; }
public string CriteriaField { get; set; }
public string PropertyType { get; set; }
public virtual CustomReport CustomReport { get; set; }
}
我需要利用这些字段在我的数据库上创建动态查询。例如:
Select BidYear From FWOBid Where BidYear = 2015
// ^ this would look like this instead
Select CriteriaField From PropertyType Where CriteriaField [Operator] CriteriaValue
但是,我可能并不总是查询同一个表,并且在大多数情况下,查询将需要在其他表上进行连接。
我已经有了where子句的通用方法:
public static IQueryable<T> Filter<T>(IQueryable<T> query, string propertyName, string propertyValue, string op)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName);
return Filter<T>(query, propertyInfo, propertyValue, op);
}
public static IQueryable<T> Filter<T>(IQueryable<T> query, PropertyInfo propertyInfo, string propertyValue, string op)
{
ParameterExpression e = Expression.Parameter(typeof(T), "e");
MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
UnaryExpression c = GetExpressionByType(propertyValue, propertyInfo.PropertyType);
BinaryExpression b = null;
if (op == "=")
{
b = Expression.Equal(m, c);
}
else if (op == "!=")
{
b = Expression.NotEqual(m, c);
}
else if (op == ">")
{
b = Expression.GreaterThan(m, c);
}
else if (op == "<")
{
b = Expression.LessThan(m, c);
}
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(b, e);
return query.Where(lambda);
}
我想象的方法是这样的:
foreach (var crit in report.CustomReportCriterias)
{
var objectName = crit.PropertyType;
var value = crit.CriteriaValue;
var type = crit.CriteriaType;
var field = crit.CriteriaField;
var op = crit.Operator;
// how to dynamically get a generic collection ?
var queryable = _context.Set<objectName>();
var results = Filter<objectName>(queryable, field, value, op);
// would then do joins if needed
}
但是,我正在努力完成从基于字符串检索数据库中的可查询的初始步骤,然后我迷失了如何在之后加入这些结果。
答案 0 :(得分:0)
看看https://dynamiclinq.codeplex.com/releases/view/109593。此库使用System.Linq.Dynamic命名空间扩展Linq库,该命名空间为常见查询方法提供基于字符串的重载,因此您可以动态构建基于字符串的过滤和分组标准。另外,我的链接中的一个比通过NuGet提供的版本更好,因为它允许您将Linq语法中的整个查询(包括要检索的记录类型)定义为一个字符串(有关一个示例,请参阅“文档”选项卡;它使用静态typeof
表达式来提供类型来解析结果,但您可以反射性地使用Type.MakeGenericType()
创建泛型类型。
问题将回到静态定义的类型;一旦你变得动态,你往往必须保持动态,使用GetProperties()枚举数据字段和GetValue / SetValue来操纵它们。有一些技巧,通常需要使用一组具体类型的重载,迫使运行时检查对象的真实类型,然后一旦对象进入其中一个重载,你就会又回到了静止世界。
答案 1 :(得分:0)
使用Entity Framework,您可以直接执行查询,并将结果映射到这样的实体。
var results = db.ExecuteStoreQuery<YourEntity>(
"SELECT * FROM YourEntities WHERE SomeColumn = @param1",
param1);