1

我正在使用 Caliburn.Micro 开发一个 Silverlight 5 应用程序(对于那些不熟悉 Caliburn 的人不要担心,你不需要了解 Caliburn 的东西才能回答我的问题)作为一个 MVVM 框架,我需要从中读取一些数据SQL 表。我选择了 WCF 数据服务(原因不重要)。

为了使事物具有通用性和可重用性,我创建了一个视图模型,它采用服务的 aDataServiceQuery<TEntity>和aURI并加载数据。我还为此视图模型创建了一个视图,使用 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 子句并且无法添加另一个过滤器)但我不知道如何解决它。

有任何想法吗 ?

4

1 回答 1

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);
        }

表达式树非常强大

于 2013-02-15T10:29:11.813 回答