Linq to NHibernate не возвращает правильные данные

у меня есть класс

public class Item : IItem
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual bool IsActive { get; set; }
}
public interface IItem
{
    Guid Id { get; set; }
    string Name { get; set; }
    bool IsActive { get; set; }
}

public class ItemMap : ClassMap<Item>
{
    public ItemMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        Map(x => x.IsActive);
    }
}

В моей базе данных я создал пять элементов. У трех флаг IsActive установлен в true, а у двух — в false.

При использовании интерфейса он возвращает все пять элементов:

        var q = from i in session.Linq<IItem>()
                where i.IsActive == true
                select i;

Однако при использовании конкретного класса он возвращает правильные три элемента:

        var q = from i in session.Linq<Item>()
                where i.IsActive == true
                select i;

EDIT
Я хотел бы вернуть интерфейс, потому что я читал, что должен возвращать неконкретные классы. Обратите внимание, что на самом деле эти запросы Linq находятся в репозитории в другом проекте (на случай, если это станет веб-приложением или приложением WPF).


person Nathan Koop    schedule 19.08.2010    source источник
comment
Ваша последняя фраза не имеет смысла. Вы можете просто создать подкласс из Item и по-прежнему использовать тип Item для доступа к экземплярам подкласса.   -  person Timwi    schedule 20.08.2010
comment
@Timwi, вы правы, я отредактирую, чтобы правильно передать намерение   -  person Nathan Koop    schedule 20.08.2010


Ответы (5)


Похоже на ошибку в старом провайдере contrib Linq.

Попробуйте с NHibernate 3, он работает как положено.

person Diego Mijelshon    schedule 19.08.2010
comment
Спасибо, @Diego, это сработало. Однако потребовалось немного побегать, чтобы восстановить сборки. stackoverflow.com/questions/2349400/ - person Nathan Koop; 22.08.2010

Я считаю, что вам нужно будет отобразить IItem вместо конкретного класса Item, чтобы эта работа работала правильно.

person DanP    schedule 19.08.2010

Что вы можете попробовать:

  • Вместо

    public class ItemMap : ClassMap<Item>
    

    использовать

    public class ItemMap : ClassMap<IItem>
    
  • Просто приведите возвращаемые объекты:

    var q = from i in session.Linq<Item>()
            where i.IsActive == true
            select (IItem)i;
    
person Timwi    schedule 19.08.2010

Я не думаю, что вам нужно беспокоиться о запросах к конкретным типам, это нормально. Просто пусть ваш метод репозитория возвращает интерфейс. Есть смысл?

public IItem GetItem(int id)
{

  var item = from i in session.Linq<Item>()
                where i.IsActive == true
                select i;

  return item;

}

Это позволит вам работать с запросами так, как должно, и позволить всему вашему зависимому коду работать с интерфейсом, который в любом случае вам действительно нужен.

person Corey Coogan    schedule 20.08.2010

Я опубликовал подобную проблему здесь и закончил тем, что бросил спящий режим (по несвязанным причинам). Я не думаю, что LINQ действительно «завершен» в спящем режиме, все еще есть некоторые методы, например, Enumerable(), которые выдают нереализованное исключение.

Однако, чтобы ответить на ваш вопрос, я обнаружил, что ДОЛЖЕН использовать конкретные классы, а не интерфейсы, потому что для интерфейса нет файла *.hbm.xml, поэтому hibernate не знает, как сопоставить интерфейс с соответствующей таблицей. Как кто-то сказал в моем посте, я, вероятно, захожу слишком далеко с этой слабой связью, поскольку вы должны использовать слабую связь и инверсию управления только в областях, где потенциально может быть много изменений, но да, модели базы данных действительно сильно меняются.

Я думаю, что ключ здесь в том, чтобы убедиться, что ваш бизнес-домен находится в своей собственной сборке «MyBusiness.Domain», и все проекты ссылаются на нее. Затем все эти проекты будут иметь указанные интерфейсы (дизайн по контракту) и конкретные классы, которые будут внедрены с помощью чего-то вроде Ninject, таким образом, вы можете создавать экземпляры новых классов в своей бизнес-области, и до тех пор, пока они реализуют соответствующие интерфейсы, ваши проекты могут их использовать.

Как вы можете видеть, я не эксперт в этом... пока... но я думаю, что этот способ разработки программного обеспечения в основном делает это правильно, и это довольно сложно в начале!

person Paul Aldred-Bann    schedule 28.09.2011