Получить только определенные столбцы при использовании запросов Critera? - PullRequest
19 голосов
/ 30 марта 2009

Я предлагаю NHibernate для проекта, который мы делаем в моей компании, и я хотел бы знать, можно ли оптимизировать NHibernate для получения только определенных столбцов в таблице при использовании языка запросов Criteria.

Например. Допустим, у меня есть таблица с 30 столбцами, и она сопоставлена ​​с объектом с помощью NHibernate, который соответствует 1-к-1 сопоставлению с таблицей. Однако для конкретной функции системы мне нужны только два из этих столбцов.

Теперь я знаю, что могу использовать HQL и выполнить CreateQuery, который выполнит это, но для этого потребуется создать конструктор для каждой комбинации полей, которые я хотел бы выборочно получить. Это может быть огромной болью с точки зрения обслуживания, так как я не поймаю недостающие конструкторы до времени выполнения.

Мне нравится язык запросов Criteria, поскольку он генерирует параметризованный SQL вместо простых запросов SQL из HQL. Я вижу, что есть модель "Исключить", которая не включает определенные столбцы, но в большинстве случаев я буду включать больше столбцов, чем исключать.

Благодаря комментарию ниже я посмотрел на прогнозы, и это все еще не совсем идеальная ситуация для меня. При использовании следующего:

var list = session
    .CreateCriteria(typeof (Task))
    .SetProjection(Projections
                       .ProjectionList()
                       .Add(Projections.Property("Id")))
    .List();

Я получаю переменную list в виде целых чисел, я бы предпочел, чтобы у меня был полный объект Task, но со всеми полями, установленными в значения по умолчанию. Это вообще возможно? Все, что я вижу до сих пор, говорит нет.

Ответы [ 5 ]

34 голосов
/ 30 марта 2009

Да, вы можете сделать это с критериями запросов, используя прогнозы. Просто спроецируйте только те свойства, которые вы хотите использовать, и только они будут включены в предложение select скомпилированного запроса.

http://nhibernate.info/doc/nh/en/index.html#querycriteria-projection

Обновление для редактирования

Есть несколько способов сделать это, однако с некоторыми ограничениями. 1) Способ NHibernate.

var list = session.CreateCriteria(typeof (Task))
.SetProjection(Projections.ProjectionList()
                   .Add(Projections.Property("Name"), "Name")
                   .Add(Projections.Property("ID"), "ID")
)
.SetResultTransformer(Transformers.AliasToBean(typeof (Task)))
.List();

Просто назначьте имя свойства в качестве псевдонима для вашей проекции, и преобразователь AliasToBean отобразит эти проекции в фактический класс. Ограничением этого метода является то, что любые сопоставляемые свойства должны иметь установщик в классе POCO, это может быть защищенный установщик, но он должен иметь установщик.

Вы также можете сделать это с помощью linq немного по-другому

var list = session.CreateCriteria(typeof (Task))
.SetProjection(Projections.ProjectionList()
                   .Add(Projections.Property("Name"))
                   .Add(Projections.Property("ID"))
)
.List<IList>()
.Select(l => new Task() {Name = (string) l[0], ID = (Guid) l[1]});

Это просто использование linq для сопоставления индексированного списка, который выводится в новый экземпляр класса Task. Применяется то же ограничение, что и выше, за исключением того, что оно немного более строгое, так как все отображаемые свойства должны иметь открытый установщик, потому что именно это использует linq для заполнения объекта.

Надеюсь, это вам поможет.

5 голосов
/ 30 марта 2009

В ответ на ваши изменения: Насколько я знаю, это невозможно.

Но, что вы можете сделать, это создать класс, который известен NHibernate и который просто содержит интересующие вас свойства.

Например, класс «TaskView», который просто содержит определенные свойства класса «Task».
Вам придется «импортировать» класс TaskView в файл hbm.xml, чтобы NHibernate знал об этом классе (см. Сопоставление импорта).
Затем вы можете использовать Projection для преобразования «Task» в экземпляр TaskView. Когда вы посмотрите на запрос, который генерирует NHibernate, вы увидите, что он будет получать только те столбцы, которые необходимы для заполнения класса TaskView.

Что-то вроде того, что я написал здесь: NHibernate и Collection Count

0 голосов
/ 06 апреля 2014

Я задал похожий вопрос, и в NHibernate, похоже, отсутствует самая распространенная функция, используемая приложениями с момента создания SQL. Возможность выбрать только несколько столбцов. Это действительно банально, и если бы я был в проекте, я бы отказался от любой логики, которая требует, чтобы вы перепрыгивали через обруч и переворачивали все вокруг, чтобы выбрать только поля. Даже если на это есть ответ, я нахожу часы исследований слишком сложными для чего-то такого простого. Я знаю, что он доступен в linq-провайдере Nhibernate, использующем проекцию, но для чрезвычайно сложных запросов это невозможно, поэтому выбирайте только определенные поля. Либо все они, либо вы должны начать создавать DTO / Модели, которые не являются оригинальными, которые, на мой взгляд, не должны дублироваться, потому что пользователь просто хочет меньше записей. Список исключений / включений для обычных запросов на основе sql (не linq) является обязательным. Я бы хотел, чтобы эти ORM сначала делали самые простые вещи. Просто игнорируйте заполнение модели, если поля не возвращены в наборе результатов из базы данных. Я надеюсь, что кто-то может дать простое решение / взломать / обойти.

0 голосов
/ 19 июля 2010

Вы пытались установить конструктор по умолчанию для установки значений по умолчанию? Так как это проблема со стороны приложения, решать вам. Кстати, зачем вам нужен конструктор для каждой перестановки? Hibernate будет использовать либо конструктор всех аргументов, либо конструктор без аргументов, а затем использовать установщики, поэтому нет необходимости выполнять всю эту работу. На самом деле это может сделать больше, чем если я правильно помню, он может даже установить все приватные поля без установщиков, если настроен правильно, хотя магия манипулирования байтовым кодом.

0 голосов
/ 30 марта 2009

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

NHibernate будет обрабатывать представление так же, как и любую таблицу, хотя, конечно, операции CRUD будут проблемой для проблем целостности данных.

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