我正在开发一个带有Caliburn.Micro的Silverlight 5应用程序(对于那些不熟悉Caliburn的人不要担心,你不需要了解Caliburn的东西才能回答我的问题)作为MVVM框架,我需要阅读SQL表中的一些数据。我选择了WCF数据服务(原因不在此处)。
为了使事情变得通用和可重用,我创建了一个视图模型,它接受服务的DataServiceQuery<TEntity>
和URI
并加载数据。我还为此视图模型创建了一个视图,使用telerik RadGridView显示数据,使用Caliburn IResult在子窗口中显示视图模型。我想使用这个视图模型和视图,只要我需要从表中选择一些东西,因为在我的应用程序中我有许多表单,其中用户需要从大型列表中选择一些字段(SQL表)。
public class SelectDBEntitiesViewModel<TEntity, TContext> : DialogScreenBase, IAmClean
where TEntity : class, new()
where TContext : DataServiceContext
{
public SelectDBEntitiesViewModel()
{
}
public void Load()
{
// load
}
public DataServiceQuery<TEntity> Query{ get; set; }
public void Filter()
{
Query = _originalQuery.AddQueryOption("$filter", "startswith(" + _filterProperty + ",'" + FilterValue + "')");
Load();
}
}
因此,从协程中的其他视图模型中我创建了这个IResult类:
public IEnumerable<IResult> SelectInternalBeneficiary()
{
SelectDBEntitiesResult<InternalBeneficiary, QMSEntities> r = new SelectDBEntitiesResult<InternalBeneficiary, QMSEntities>(_oDataUri);
r.Query = (from ib in r.DataContext.InternalBeneficiaries where (ib.Firma == Model.GroupCompany) select ib) as DataServiceQuery<InternalBeneficiary>; r.PageSize = 2;
r.ColumnSettingsName = UserSettings.SEL_INTERNALBENEFICIARIES_GRID;
r.Header = "SELECT AN INTERNAL BENEFICIARY";
r.Subtitle = "List of all departments";
yield return r;
Model.InternalBeneficiary = r.SelectedObject.DenumireDepartament;
}
因此,当此方法运行时,子窗口打开,视图模型加载数据并加载视图中的网格。
现在一切正常但是在视图中我在右上角有一个文本框,我想通过在查询中添加一些新子句来过滤数据。我需要在我的通用SelectDBEntitiesViewModel
中进行此操作,但问题是此视图模型正在使用的查询是从外部作为参数接收的。我在Filter方法中尝试了以下内容:
Query = _originalQuery.AddQueryOption("$filter", "startswith(" + _filterProperty + ",'" + FilterValue + "')");
但是当我运行应用程序时,我当然会遇到这个错误:
Can't add query option '$filter' because it would conflict with the query options from the translated Linq expression.
我理解发生了什么(我在查询中已经有一个where子句,无法添加其他过滤器)但我不知道如何解决它。
有什么想法吗?
答案 0 :(得分:0)
没关系,我设法了解如何创建Expressions
并将其添加到Query
:
此方法将带有过滤类型的启动添加到IQueryable<T>
private IQueryable<T> StartsWithQuery<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo)
{
ParameterExpression e = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");
MemberExpression m = System.Linq.Expressions.Expression.MakeMemberAccess(e, propertyInfo);
ConstantExpression c = System.Linq.Expressions.Expression.Constant(propertyValue, typeof(string));
MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
System.Linq.Expressions.Expression call = System.Linq.Expressions.Expression.Call(m, mi, c);
Expression<Func<T, bool>> lambda = System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(call, e);
return query.Where(lambda);
}
此方法将等于过滤类型添加到IQueryable<T>
:
private IQueryable<T> EqualsQuery<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo)
{
Expression<Func<T, bool>> additionalExpression =
System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(
System.Linq.Expressions.Expression.Equal(
System.Linq.Expressions.Expression.MakeMemberAccess(
System.Linq.Expressions.Expression.Parameter(typeof(TEntity), "te"),
typeof(TEntity).GetProperty(_filterProperty)),
System.Linq.Expressions.Expression.Constant(FilterValue)),
System.Linq.Expressions.Expression.Parameter(typeof(TEntity), "te"));
return query.Where(additionalExpression);
}
表达式树非常强大