1

我一直无法让这个通用的休眠查询工作,因为我不断得到:

从范围''引用的'Product'类型的变量'p',但未定义

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

我尝试了以下各种方法: 从范围引用的“产品”类型的变量“x”,但未定义NHibernate:通用方法中的QueryOver带有 nHibernate 的通用存储库从范围引用但未定义的 LambdaExpression 变量LINQ 表达式。从范围引用的类型的变量“p”,但未定义

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

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 可以是 Guid(例如 Id)或字符串(例如 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=> 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 到 String (并不奇怪 Guid 到 string 不适用于 nhibernate),第三个是 Guid 到 String 到 string,这将改变 b 而不仅仅是收集数据。

有什么办法可以让它接受字符串、Guids、整数和任何其他数据类型,同时仍然能够接受任何类型的产品?还是我仅限于制作多个版本的查询?

谢谢!

4

1 回答 1

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>>

您的调用代码如下所示:

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();
}
于 2013-10-08T01:59:54.980 回答