Подтвердить что ты не робот

Странный linq to nhibernate issue, Недопустимый листинг из 'System.Int32'

Вызов 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()}

(пространства ясности опущены)

2nd Edit: похоже, когда он пытается конвертировать между IEntity и типом экземпляра (TEntity)

здесь IEntity:

public interface IEntity
{
    int Id { get; }
}

3rd Edit: похоже, Convert (x), что приводит к тому, что AssociationVisitor неправильно посещает дерево выражений и конвертирует "Convert (x).Id"

4th Edit: И вот мы идем, некоторые уже нашли ошибку https://nhibernate.jira.com/browse/NHLQ-11!

Спасибо

Эндрю

4b9b3361

Ответ 1

Я считаю, что проблема в том, что 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();
}

Update:

Если вы не хотите иметь дело с выражениями (они могут быть сложными!), вы можете использовать библиотеку Dynamic 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();
}

Ответ 2

Я столкнулся с этим в прошлом и обычно сводится к полю в таблице базы данных, которую вы читаете, не в совместимом формате. Подобно booleans, они не преобразуются в целые числа.

Проверьте типы полей в таблице и убедитесь, что они совместимы. Может быть, ваш столбец Id является BIGINT?

Ответ 3

У меня такая же проблема: (

Не работает следующее.

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

Ответ 4

Ошибка была зарегистрирована, но еще не исправлена:

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

Я опубликовал простой тестовый пример, чтобы воспроизвести его.

Пусть надеется, что он скоро будет рассмотрен!