Restrictions.On(_func) - 从范围''引用的'Product'类型的变量'p',但它没有在passthrough上定义

时间:2013-10-07 22:35:52

标签: c# linq nhibernate generics linq-to-nhibernate

我一直无法让这个通用的nhibernate查询工作,因为我一直在努力:

从“范围”引用的“产品”类型的变量“p”,但未定义

我已经摆弄了这个问题的大量不同答案,我想我明白这个问题是什么,我只是不确定如何解决它。据我所知,'p'存在于原始范围内,但在它到达nhibernate queryover命令时停止存在,所以由于Linq按名称引用对象,它实际上不知道我在说什么了

我尝试了各种方法: variable 'x' of type 'Product' referenced from scope, but it is not defined; NHibernate : QueryOver in generic method; Generic Repository with nHibernate; LambdaExpression Variable Referenced From Scope But Not Defined; LINQ expressions. Variable 'p' of type referenced from scope, but it is not defined

不幸的是,这些都没有提供能够解决问题的答案。查询:

public class ProductsInformationQuery<T>: Query<T> where T:Product
{
    private readonly List<string> _ids;
    private readonly Expression<Func<T, object>> _func;

    public ProductsInformationQuery(List<string> ids, 
        FeaturedIdType featureIdType, Expression<System.Func<T,object>> func)
    {
        _ids = ids;
        _func = func;
    }

    public override List<T> Execute()
    {
        return Session.QueryOver<T>().Where(Restrictions.On<T>(_func).IsIn(_ids.Select(i => i).ToList())).List().ToList();
    }
}

这将获取字符串列表并检查数据库中的特定查询。这将允许我们尝试检查数据库中的一组ID; ID可以是Guids(例如Id)或Strings(例如Name)。

主叫代码:

private List<Product> LoadProducts(List<string> ids)
    {
        System.Linq.Expressions.Expression<Func<Product, object>> function = b => b.Id.ToString();
        return _productsRepository.Execute(new ProductsInformationQuery<Product>(ids, FeaturedIdType.ProductId,function)).ToList();
    }

此代码需要能够发送'b =&gt; b.Id.ToString()'作为它需要检查的函数。然后,QueryOver命令需要按其Id查找产品。产品是继承链的顶级,所以我希望能够通过数据库中的各种类型的信息找到各种类型的产品。

有趣的是,我可以让以下工作:

return Session.QueryOver<T>().Where(Restrictions.On<T>(b=>b.Id).IsIn(_ids.Select(Guid.Parse).ToList())).List().ToList();

但不是以下两个:

return Session.QueryOver<T>().Where(Restrictions.On<T>(b=>b.Id).IsIn(_ids)).List().ToList();

((AOD异常))

return Session.QueryOver<T>().Where(Restrictions.On<T>(b=>b.Id.ToString()).IsIn(_ids)).List().ToList();

((高于错误;“类型为......的变量'b'))

前者是Guid与Guid的比较,第二个是Guid to String(并不感到惊讶Guid to string不能与nhibernate一起使用)而第三个是Guid into String to string,这将改变b而不仅仅是收集数据。

有没有办法让它采用字符串和Guids和整数以及任何其他数据类型,同时仍然能够接收任何类型的产品?或者我仅限于制作几个版本的查询?

谢谢!

1 个答案:

答案 0 :(得分:0)

我会在您的类中添加一个泛型类型参数TIdType,表示您要使用的ID的类型。这最终会看起来像这样:

public class ProductsInformationQuery<TResultType, TIdType>: Query<TResultType> 
    where TResultType : Product
{
    private readonly List<TIdType> _ids;
    private readonly Expression<Func<TResultType, object>> _func;

    public ProductsInformationQuery(
        List<TIdType> ids, 
        FeaturedIdType featureIdType, 
        Expression<System.Func<TResultType, TIdType>> func)
    {
        _ids = ids;

        System.Linq.Expressions.Expression converted = 
            System.Linq.Expressions.Expression.Convert(func.Body, typeof(object));

        _func = System.Linq.Expressions.Expression.Lambda<Func<TResultType, object>>
           (converted, func.Parameters);
    }

    public override List<TResultType> Execute()
    {
        return Session.QueryOver<TResultType>()
            .Where(Restrictions.On<TResultType>(_func)
                .IsIn(_ids.ToArray())
            .List()
            .ToList();
    }
}

我使用代码将Expression<Func<TResultType, TIdType>>转换为Expression<Func<TResultType, object>> this answer

您的主叫代码如下所示:

private List<Product> LoadProducts(List<string> ids)
{
    System.Linq.Expressions.Expression<Func<Product, Guid>> function = b => b.Id;
    return _productsRepository.Execute(
        new ProductsInformationQuery<Product, Guid>
           (ids, FeaturedIdType.ProductId, function))
       .ToList();
}