0

Предположим, у меня есть следующие классы:FluentNhibernate Критерии LeftOuterJoin Создает повторяющиеся строки

public class Fund : EntityBase 
{    
    public virtual string Name { get; set; } 
    public virtual IList<FundDetail> FundDetails { get; set; } 
    public virtual IList<FundAlias> FundAliases { get; set; } 

    public Fund() 
    { 
     FundDetails=new List<FundDetail>(); 
     FundAliases=new List<FundAlias>();  
    } 
} 

public class FundDetail : EntityBase 
{ 
    public virtual string Symbol { get; set; } 
    public virtual Fund Fund { get; set; } 
} 

public class FundAlias : EntityBase 
{ 
    public virtual string Symbol { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Fund Fund { get; set; } 
} 

Мой запрос:

filterValue = "SOMETEXT"

var criteria = session.CreateCriteria<Fund>(); 
criteria.CreateAlias("FundDetails", "fd", JoinType.LeftOuterJoin); 
criteria.CreateAlias("FundAliases", "fa", JoinType.LeftOuterJoin); 

criteria.Add(
    Restrictions.InsensitiveLike("fd.Symbol", filterValue, MatchMode.Anywhere) || 
    Restrictions.InsensitiveLike("Name", filterValue, MatchMode.Anywhere) || 
    Restrictions.InsensitiveLike("fa.Symbol", filterValue, MatchMode.Anywhere)); 

criteria.SetFirstResult(0).SetMaxResults(100); 
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
var list = criteria.List<Fund>(); 

Я стараюсь, чтобы получить все фонд где название фонда или символ из фондаDetail или символ из FundAlias ​​содержит filterValue, который является простой строкой и получает 100 результатов.

Поскольку LeftOuterJoin создал дубликаты строк фонда, а потому, что в сгенерированном запросе (синтаксисе SQL) нет " criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());", несмотря на то, что есть более 100 результатов, я не получаю 100 строк, я получаю различное количество в соответствии с тем, как много строк были дублированы. я тарой, чтобы сделать это с «Проекции»:

criteria.SetProjection(
    Projections.Distinct(Projections.ProjectionList() 
     .Add(Projections.Alias(Projections.Property("Name"), "Name")) 
     .Add(Projections.Alias(Projections.Property("Id"), "Id")) 
    ) 
); 

, но я не нашел, как SetProjections Для коллекции с помощью CriteriaNote:

Что я делаю не так ли это, почему сделать это, используя критерии?

Примечание: Пожалуйста, не то, чтобы я не хотел этого делать с помощью QueryOver, мне нужно это с критериями.

ответ

1
var subquery = DetachedCriteria.For<Fund>() 
    .CreateAlias("FundDetails", "fd", JoinType.LeftOuterJoin) 
    .CreateAlias("FundAliases", "fa", JoinType.LeftOuterJoin) 
    .Add(
     Restrictions.InsensitiveLike("fd.Symbol", filterValue, MatchMode.Anywhere) || 
     Restrictions.InsensitiveLike("Name", filterValue, MatchMode.Anywhere) || 
     Restrictions.InsensitiveLike("fa.Symbol", filterValue, MatchMode.Anywhere)) 
    .SetProjection(Projections.Distinct(Projections.Id())); 

var funds = session.CreateCriteria<Fund>() 
    .Add(Subqueries.PropertyIn(Projections.Id()).In(subquery)) 
    .SetFetchMode("FundDetails", FetchMode.Eager) // for example 
    .OrderBy(Projections.Id()) 
    .SetFirstResult(0).SetMaxResults(100) 
    .SetResultTransformer(Transformers.DistinctRootEntity()) 
    .List<Fund>(); 
+0

Большое спасибо, этот метод был в моем сознании, как насчет выполнения этого подзапроса, не так ли? также не могли бы вы объяснить, почему я получаю повторяющиеся результаты? – MDDDC

+0

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