Linq to NHibernate не возвращает правильные данные - PullRequest
0 голосов
/ 20 августа 2010

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

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;

РЕДАКТИРОВАТЬ
Я хотел бы вернуть интерфейс, потому что я прочитал, что должен возвращать неконкретные классы.Обратите внимание, что на самом деле эти запросы Linq находятся в хранилище в другом проекте (в случае, если это веб-приложение или приложение WPF)

Ответы [ 5 ]

1 голос
/ 20 августа 2010

Похоже, что это ошибка старого поставщика Linq contrib.

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

0 голосов
/ 28 сентября 2011

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

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

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

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

0 голосов
/ 20 августа 2010

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

public IItem GetItem(int id)
{

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

  return item;

}

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

0 голосов
/ 20 августа 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;
    
0 голосов
/ 20 августа 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...