奇怪的linq到nhibernate问题,来自“System.Int32”的无效强制转换

奇怪的linq到nhibernate问题,来自“System.Int32”的无效强制转换,nhibernate,linq-to-nhibernate,Nhibernate,Linq To Nhibernate,在以下代码中调用Get可以正常工作: public class ContractService : IContractService { private readonly IRepository<Contract> repository; public ContractService(IRepository<Contract> repository) { this.repository = repository; }

在以下代码中调用Get可以正常工作:

public class ContractService : IContractService
{
    private readonly IRepository<Contract> repository;

    public ContractService(IRepository<Contract> repository)
    {
        this.repository = repository;
    }

    public Contract Get(int contractId)
    {
        return repository.Query().Where(x => x.Id == contractId).FirstOrDefault();
    }
有人知道为什么吗

编辑:以下是不同表达式的外观:

在泛型版本top one中,它似乎出于某种原因试图转换x,这一定是因为泛型:s

{value(NHibernate.Linq.Query`1[Contract]).Where(x => (Convert(x).Id = value(CRUDService`1+<>c__DisplayClass0[Contract]).Id)).FirstOrDefault()}

{value(NHibernate.Linq.Query`1[Contract]).Where(x => (x.Id = value(ContractService+<>c__DisplayClass2).Id)).FirstOrDefault()}
第三次编辑:似乎是Convertx导致AssociationVisitor无法正确访问表达式树并转换Convertx.Id

第四次编辑:我们开始了,有些人已经发现了错误

谢谢


Andrew

我以前遇到过这个问题,它通常归结为您正在读取的数据库表中的字段格式不兼容。就像布尔运算一样,它不会转换成整数


检查表中的字段类型,确保它们兼容。也许你的Id列是一个BIGINT

我认为问题在于Linq/NHibernate试图将ienty.Id映射到表列,而不是tenty.Id。我在LinqToSql存储库实现中遇到了这个问题。解决方法是使用这样一个表达式:

private static Expression<Func<TEntity, bool>> GetFindExpression(string propertyName, object value)
{
    ParameterExpression parameterExpression = Expression.Parameter(typeof (TEntity), "id");
    MemberExpression propertyExpression = Expression.Property(parameterExpression, propertyName);

    Expression bodyExpression = Expression.Equal(propertyExpression, Expression.Constant(value));

    return Expression.Lambda<Func<TEntity, bool>>(bodyExpression, parameterExpression);
}
更新:

如果你不想处理表达式,它们可能会很棘手!,您可以使用动态LINQ库,如Scott Guthrie所述:

这会将Getid更改为:

public TEntity Get(int id)
{
    var entities = Query.Where(GetFindExpression("Id", id));
    return entities.FirstOrDefault();
}
public TEntity Get(int id)
{
    var entities = Query.Where("Id = @0", id);
    return entities.FirstOrDefault();
}

我也有同样的问题:

以下方法不起作用

public override T Load(int id)
{
    return (from t in _sessionFactory.Session.Linq<T>()
            where t.ID == id 
            select t).SingleOrDefault();
}
下面是一个例子

public override Product Load(int id)
{
    return (from t in _sessionFactory.Session.Linq<Product>()
            where t.ID == id
            select t).SingleOrDefault();
}

该错误已报告,但尚未修复:

我发布了一个简单的测试用例来复制它


希望它能尽快得到解决

听起来确实很奇怪。您是否有正在执行的SQL的日志?堆栈跟踪的其余部分是什么样子的?似乎没有运行SQL,看起来Linq在接近DB之前就失败了。我刚刚下载了调试的源代码,我也遇到了这个问题!Linq to NHibernate目前正在重写,我一直在处理这个问题,直到它发布。我同意这可能会导致无效的强制转换异常,但这不是这里发生的事情。阅读jira的代码和错误报告。这是由generics引起的一个bug我认为问题在于Linq/NHibernate试图将IEntity.Id映射到表列,而不是TEntity.Id。我完全同意。我喜欢转换lambda的想法,我将尝试制作一个通用版本,它将处理所有转换。。。我注意到你添加了一个测试用例,做得不错。希望他们能尽快解决这个问题!
public TEntity Get(int id)
{
    var entities = Query.Where("Id = @0", id);
    return entities.FirstOrDefault();
}
public override T Load(int id)
{
    return (from t in _sessionFactory.Session.Linq<T>()
            where t.ID == id 
            select t).SingleOrDefault();
}
public override Product Load(int id)
{
    return (from t in _sessionFactory.Session.Linq<Product>()
            where t.ID == id
            select t).SingleOrDefault();
}