12

在以下代码中调用 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();
    }

但是当我这样做时:

public class ContractService : CRUDService<Contract>, IContractService
{
    public ContractService(IRepository<Contract> repository) : base(repository)
    {
    }
}


public class CRUDService<TEntity> : ICRUDService<TEntity> where TEntity : IEntity
{
    protected readonly IRepository<TEntity> repository;

    public CRUDService(IRepository<TEntity> repository)
    {
        this.repository = repository;
    }

    public TEntity Get(int id)
    {
        var entities = this.repository.Query().Where(s => s.Id == id);
        return entities.FirstOrDefault();
    }

get 方法中的“实体”在您迭代它时会引发异常:

Invalid cast from 'System.Int32' to 'TEntity' (where TEntity is the type name)

有人知道为什么吗?

编辑:这是不同的表达方式:

在泛型版本(顶部)中,它似乎出于某种原因试图转换 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()}

(为清楚起见省略了命名空间)

第二次编辑:似乎是当它尝试在 IEntity 和实例类型(TEntity)之间进行转换时

这是 IEntity:

public interface IEntity
{
    int Id { get; }
}

第三次编辑:似乎是导致 AssociationVisitor 无法正确访问表达式树并转换“Convert(x).Id”的 Convert(x)

第四次编辑:我们走了,有人已经发现了这个错误https://nhibernate.jira.com/browse/NHLQ-11

谢谢

安德鲁

4

4 回答 4

3

我认为问题在于 Linq/NHibernate 试图将 IEntity.Id 映射到表列而不是 TEntity.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);
}

所以这会将 Get(id) 更改为:

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

更新:

如果您不想处理表达式(它们可能很棘手!),您可以使用 Scott Guthrie 在此处描述的动态 LINQ 库: http ://weblogs.asp.net/scottgu/archive/2008/01/ 07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

这会将 Get(id) 更改为:

public TEntity Get(int id)
{
    var entities = Query.Where("Id = @0", id);
    return entities.FirstOrDefault();
}
于 2009-03-19T16:21:22.670 回答
1

我有同样的问题 :(

以下不起作用。

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();
}
于 2009-05-21T06:49:56.627 回答
1

我过去遇到过这种情况,通常归结为您正在阅读的数据库表中的字段格式不兼容。就像布尔值不转换为整数一样。

检查表中的字段类型并确保它们兼容。也许您的 Id 列是 BIGINT?

于 2009-03-18T19:23:45.743 回答
1

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

https://nhibernate.jira.com/browse/NHLQ-11

我发布了一个简单的测试用例来重现它。

让我们希望它尽快得到解决!

于 2009-08-07T10:44:36.603 回答