2014-11-27 11 views
3

Я попытался обновить NH 3.3.1.4000 до последней версии NH 4.0.2.4000, и у меня возникла проблема с FetchMany и ThenFetchMany.Обновление NHibernate 4 - Не удается одновременно получить несколько пакетов

В этом посте я узнал, что эта старая функциональность больше не действительна, Breaking changes with NHibernate 4 upgrade.

Каков правильный способ сделать этот выбор в новой версии NH?

Пример кода:

var IdsList = new List { /* Some Ids */ }; 
session.Query<A>() 
.FetchMany(x=>x.B_ObjectsList) 
.ThanFetchMany(x=>x.C_ObjectsList) 
.Where(x=>IdsList.Contains(x=>x.Id)) 
.ToList(); 

Классы:

Public Class A 
{ 
    public int Id {get;set;} 
    public IList<B> B_ObjectsList{get;set;} 
} 

Public Class B 
{ 
    public int Id {get;set;} 
    public IList<C> C_ObjectsList {get;set;} 
} 

Public Class C 
{ 
    public int Id {get;set;} 
} 

Mapping:

<class name="A" table="A"> 
<id name="Id" type="int" column="Id" unsaved-value="0"> 
    <generator class="identity" /> 
</id> 
<bag name="B" table="B" inverse="false" lazy="true" 
cascade="all-delete-orphan"> 
</class> 

<class name="B" table="B"> 
<id name="Id" type="int" column="Id" unsaved-value="0"> 
    <generator class="identity" /> 
</id> 
<bag name="C" table="C" inverse="false" lazy="true" 
cascade="all-delete-orphan"> 
</class> 


<class name="C" table="C"> 
<id name="Id" type="int" column="Id" unsaved-value="0"> 
    <generator class="identity" /> 
</id> 
</class> 

ответ

1

вероятно

var IdsList = new List { /* Some Ids */ }; 
var results = session.Query<A>() 
    .FetchMany(x => x.B_ObjectsList) 
    .Where(x=>IdsList.Contains(x.Id)) 
    .ToList(); 

// initialize C_ObjectsList 
var bIds = results.SelectMany(x => x.B_ObjectsList).Select(b => b.Id).Distinct().ToList(); 
session.Query<B>() 
    .FetchMany(x => x.C_ObjectsList) 
    .Where(b => bIds.Contains(b.Id)) 
    .ToList(); 

return results; 
+0

Спасибо, я проверил, и он работает. Но если я использую дальше, он не работает, могу ли я сделать такой выбор, не запрашивая базу данных для каждого соединения? –

+1

с sql есть только 2 возможности: большой декартовой продукт или запрос для каждого уровня ассоциации. Первый часто приводит к большим результатам легко, поэтому, вероятно, причина его удаления. если все ассоциации находятся на одном уровне, вы можете использовать Фьючерсы для сокращения обращений к базе данных. – Firo

+0

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

0

Если B имеет ссылку на А вы можете сделать:

var IdsList = new List { /* Some Ids */ }; 
var results = session.Query<A>() 
        .Fetch(a => a.B_ObjectsList) 
        .Where(a => IdsList.Contains(a.Id)) 
        .ToList(); 

// initialize C_ObjectsList 
var aQuery = session.Query<A>() 
        .Where(x => IdsList.Contains(x.Id)); 

session.Query<B>() 
     .Fetch(b => b.C_ObjectsList) 
     .Where(b => aQuery.Contains(b.A) 
     .Prefetch(); 

Это имеет то преимущество, что не ограничивается макс параметров БД, которые в SQL-сервера по умолчанию для 2100. Вместо ToList(), я использую этот метод расширения:

static public void Prefetch<T>(this IQueryable<T> query) 
{ 
    // ReSharper disable once ReturnValueOfPureMethodIsNotUsed 
    query.AsEnumerable().FirstOrDefault(); 
}