Pytanie dziwny problem z linq do nhibernate, Niepoprawny rzut z 'System.Int32' [closed]


Wywoływanie Poniższy kod działa poprawnie:

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

ale kiedy to zrobię:

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

"entity" wewnątrz metody get zgłasza wyjątek podczas iteracji:

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

Ktoś ma pojęcie, dlaczego?

Edytuj: oto, jak wyglądają różne wyrażenia:

W wersji ogólnej (na górze), wydaje się, że próbujesz przekonwertować x z jakiegoś powodu, który musi być spowodowany przez generyczne: 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()}

(przestrzenie nazw zostały pominięte dla jasności)

2nd Edit: Wygląda na to, że próbuje konwertować pomiędzy IEntity a typem instancji (TEntity)

tutaj jest IEntity:

public interface IEntity
{
    int Id { get; }
}

3rd Edit: wygląda na to, że Convert (x) powoduje, że AssociationVisitor nie odwiedza poprawnie drzewa wyrażeń i konwertuje "Convert (x) .Id"

4th Edit: I już idziemy, ktoś już znalazł błąd https://nhibernate.jira.com/browse/NHLQ-11!

Dzięki

Andrzej


12
2018-03-10 09:49


pochodzenie


To brzmi bardzo dziwnie. Czy masz jakieś dzienniki dotyczące tego, co SQL jest wykonywane? Jak wygląda reszta śladu stosu? - Jon Skeet
Wydaje się, że żaden SQL nie jest uruchamiany, wygląda na to, że Linq zawodzi, zanim dotrze do bazy danych. Właśnie pobrałem źródło do debugowania sourceforge.net/project/... - Andrew Bullock
Też wpadłem na ten problem! - bleevo
Linq do NHibernate jest obecnie przepisywany, pracuję nad tym do czasu jego wydania. - Andrew Bullock


Odpowiedzi:


Wierzę, że problem polega na tym, że Linq / NHibernate próbuje odwzorować IEntity.Id na kolumnę tabeli zamiast TEntity.Id. Miałem ten problem z implementacją repozytorium LinqToSql. Sposób obejścia to użycie takiego wyrażenia:

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

To zmieniłoby Get (id) na:

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

Aktualizacja:

Jeśli nie chcesz zajmować się wyrażeniami (mogą być trudne!), Możesz użyć biblioteki Dynamic LINQ opisanej przez Scotta Guthriego tutaj: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

To zmieniłoby Get (id) na:

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

3
2018-03-19 16:21



"Uważam, że problem polega na tym, że Linq / NHibernate próbuje odwzorować IEntity.Id na kolumnę tabeli zamiast TEntity.Id." W pełni się zgadzam. Podoba mi się pomysł transformacji lambda, spróbuję stworzyć ogólną wersję, która obsłuży wszystkie transformacje ... bądź na bieżąco - Andrew Bullock


Wpadłem na to w przeszłości i zwykle sprowadza się do pola w tabeli bazy danych, którą czytasz, nie ma kompatybilnego formatu. Podobnie jak booleans nie konwertuj na liczby całkowite.

Sprawdź typy pól w tabeli i upewnij się, że są one zgodne. Może twoja kolumna ID jest BIGINT?


1
2018-03-18 19:23



Zgadzam się, że może to spowodować wyjątek "nieprawidłowej obsady", ale to nie jest tutaj. Przeczytaj kod i raport o błędzie na jira. To błąd spowodowany przez generyczne - Andrew Bullock


Mam ten sam problem :(

Poniższe nie działa.

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

Oto co robi!

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

1
2018-05-21 06:49





Błąd został zgłoszony, ale jeszcze nie został naprawiony:

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

Wysłałem prosty test, aby go odtworzyć.

Miejmy nadzieję, że wkrótce otrzymamy odpowiedź!


1
2017-08-07 10:44



zauważyłem, że dodałeś przypadek testowy, fajną pracę. Mam nadzieję, że wkrótce to naprawią! - Andrew Bullock