powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / nhibernate как сделать join с дополнительной таблицей в mapping?
17 сообщений из 17, страница 1 из 1
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39084991
Vadim999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Столкнулся с проблемой что NH втихаря генерирует плохой запрос с IN, который казалось бы не должен возникать, но NH думает что так лучше :)
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Рассмотрим такую схему классов:
class User{
    public IList<Payment> Payments {get;set;}
}
class Payment{
    public User User {get;set;}
    public Product Product  {get;set;}
    public decimal Sum {get;set;}
}
class Product{
    public Name {get;set;}
}

Для User объявлен маппинг:
mapping.HasMany(x => x.UserServicePayments)



Получается что при первом обращении к User.Payments в эту коллекцию загружаются все оплаты пользователя. Все работает как задумано и все последующие запросы типа:
Код: c#
1.
user.Payments.Where(x=>x.Sum > 1000).ToArray() 


работают как положено, не генерируя лишний SQL, т.к. все Payment в коллекции.

НО! Когда я делаю запрос чуть глубже чем Payment, например:
Код: c#
1.
user.Payments.Where(x=>x.Product.Name == n).ToArray()


то это приводит к генерации очень плохого запроса. NH берет все ProductId из коллекции user.Payments и запрашивает их:
select * from Product where id in (1,2,3,3,4... тут все id из user.Payments)
в плане такой запрос не позволяет использовать индекс, т.к. IN достаточно длинный, что приводит к full scan и падению системы по timeout. Вручную написать запрос с хинтом WITH(INDEX(MyIndex)) - не вариант.

Выходом я вижу как-то указать в маппинге для User, что вместе с Payment для поля Payments нужно загрузить ещё и Product. Примерно так:
mapping.HasMany(x => x.UserServicePayments).Join(x=>x.Product)
Но как это написать на fluetn nhibernate не пойму.
Спасибо!
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085002
Vadim999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Другими словами я хочу чтобы NH при инициализации коллекции user.Payments делал запрос:
Код: sql
1.
select prod.*, pay.* from Payment pay inner join Product prod on pay.ProductId = prod.Id where pay.UserId = @p
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085202
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vadim999то это приводит к генерации очень плохого запроса. NH берет все ProductId из коллекции user.Payments и запрашивает их

эта потому что NHibernate унылое преунылое УГ...

попробуй не обращаться к навигационным коллекциям хибера.. никогда, тащи запросы из сессии, с критериями, через LINQ-обёртку и прочую ерунду.

в EF зато всё работает правильно и красиво :)

П.С. да, я типа пропаганду веду тута, ох уж это засилье убожественного NH-а...
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085262
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttэта потому что NHibernate унылое преунылое УГ

это потому что надо внимательно читать документацию

http://nhibernate.info/doc/nh/en/index.html#persistent-classes-tuplizers
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085266
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
маппинг, скорее всего кривой. делать для такого объекта коллекцию как свойство и мапить её - не правильно. смысл коллекции в маппинге, что она должна грузиться вместе с объектом, типа "табличная часть документа". а так можно сдуру и всю базу выкачать
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085267
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
class User{
    public IList<Payment> Payments {get;set;} //зачем?
}
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085270
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttв EF зато всё работает правильно и красиво :)

он просто ограниченее, пока. и не позволяет (пока) на такие грабли натыкаться.
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085279
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
user.Payments.Where(x=>x.Product.Name == n).ToArray()



какой-то переворот с подвыподвертом. надо писать нормальный Criteria, ну или чем вы там пользуетесь. linq в NH вроде не особо поддерживается
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085280
Vadim999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторэта потому что NHibernate унылое преунылое УГ...

попробуй не обращаться к навигационным коллекциям хибера.. никогда, тащи запросы из сессии, с критериями, через LINQ-обёртку и прочую ерунду.

Я конечно же избегаю обращаться к навигационным коллекциям. Но к сожалению это очередной старый проект, который мне дали на сопровождение. Там ВСЯ бизнес логика находится внутри POCO. Медленно и верно переношу её в слой сервисов, но это влечет за собой массивные рефакторинги с изменением сотен файлов.
Просто в этот раз хотелось не бить блох утюгом, а обойтись малой кровью...

авторpublic IList<Payment> Payments {get;set;} //зачем?
Было :) Там конечно сильно сложнее, лишь максимально упростил пример.
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085281
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть ощущение, что Where(x=>x.Product.Name == n) - это не доменная логика
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085283
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vadim999Медленно и верно переношу её в слой сервисов

даже страшно представить, что тогда там в этих "POCO"
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085284
Vadim999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторесть ощущение, что Where(x=>x.Product.Name == n) - это не доменная логика
Ну значит вы не знаете как мне сделать маппинг. Жаль.
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085285
Vadim999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
автордаже страшно представить, что тогда там в этих "POCO"
POCO такие большие что студия тормозит при скролле и их пришлось нарезать на partial classes :)
Классический enterprise. 500 полей в каждой сущности :)
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085286
kmaw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vadim999500 полей в каждой сущности

ну это нормально
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085655
maratoss
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JoinQueryOver тебе нужен

Получится типа такого:

Код: c#
1.
2.
3.
4.
5.
6.
7.
// это
user.Payments.Where(x=>x.Product.Name == n)

// заменить на это
session.QueryOver<User>
	.JoinQueryOver(x => x.Payments)
	.Where(x=>x.Product.Name == n)
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39085663
Vadim999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дорогой товарищ! Я прекрасно знаю как писать запросы через ISession и я бы с радостью так сделал, но в том месте программы где мне нужно я не могу его получить, без массивного рефакторинга.
...
Рейтинг: 0 / 0
nhibernate как сделать join с дополнительной таблицей в mapping?
    #39091612
Vadim999
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ларчик то просто открывался, ребята.
Можно ведь указать чтобы Payment всегда джойнил Product с помощью:
Код: c#
1.
paymentMapping.References(x => x.Product).Fetch.Join();


Это приводит к жадному джойну с продуктами, хотя местами это замедлит работу, но с целом в моем случае это спасение.
Удивительно, что это не помогало:
Код: c#
1.
paymentMapping.References(x => x.Product).Not.LazyLoad();
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / nhibernate как сделать join с дополнительной таблицей в mapping?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]