2011-11-01 75 views
0

我有一個奇怪的要求,我不知道如何解決。跨多個實體查詢

假設下面的類定義:

public class Client 
{ 
    public Guid Id { get; set; } 
    public String Person { get; set; } 
    public IList<Client> SecondaryClients { get; set; } 
    public Client PrimaryClient { get; set; } 
} 

public class Person 
{ 
    public Guid Id { get; set; } 
    public String Name { get; set; } 
} 

當用戶搜索的名字的客戶機系統,它需要搜索所有主要的客戶,以及是一個躍距二次客戶。 (即如果PrimaryClient設置,那麼我們需要檢查PrimaryClient.Person.Name財產,但我們不必擔心PrimaryClient.PrimaryClient。)

使用DetachedCriteria之後,我有以下幾點:

var clientQuery = DetachedCriteria.For<Client>(); 
      clientQuery.Add(Restrictions.Disjunction() 
           .Add(Restrictions.Like("Person.Surname", lastName, MatchMode.Start)) 
           .Add(Restrictions.Like("PrimaryClient.Person.Surname", lastName, MatchMode.Start)) 
           .Add(Restrictions.Like("SecondaryClients.Person.Surname", lastName, MatchMode.Start))); 
      var session = OpenSession(); 
      session.BeginTransaction(); 
      var clients = clientQuery.GetExecutableCriteria(session).Future<Client>(); 
      session.Transaction.Commit(); 
      session.Close(); 

現在顯然,這是關閉的。做一些挖掘我發現我需要設置別名。首先是容易找到Person.Surname:

var clientQuery = DetachedCriteria.For<Client>(); 
     clientQuery = clientQuery.CreateAlias("Person", "p"); 
     clientQuery.Add(Restrictions.Disjunction() 
          .Add(Restrictions.Like("p.Surname", lastName, MatchMode.Start)) 
          .Add(Restrictions.Like("PrimaryClient.Person.Surname", lastName, MatchMode.Start)) 
          .Add(Restrictions.Like("SecondaryClients.Person.Surname", lastName, MatchMode.Start))); 
     var session = OpenSession(); 
     session.BeginTransaction(); 
     var clients = clientQuery.GetExecutableCriteria(session).Future<Client>(); 
     session.Transaction.Commit(); 
     session.Close(); 

但是,對於我的生活,我不知道我能爲PrimaryClient.Person的別名做。我在這裏走錯了路嗎?任何幫助,將不勝感激。

注:我最初忘了提及。 SecondaryClient和PrimaryClient可能爲空。

+0

我覺得你的類的設計是不完美的,我的意思是,有一個PrimaryClient,並有一些SecondaryClients的客戶端類。在我看來似乎有點奇怪。 – Rashad

+0

我完全同意。令人遺憾的是,我在開發週期的晚些時候進入了這個項目,並沒有就如何設計事情發表意見。 – rie819

回答

0

對於那些保持分數,我能夠弄清楚如何做到這一點。我不確定是否有更有效的方法,但是這裏是我使用DetachedCriteria設置查詢的方式。

var clientQuery = DetachedCriteria.For<Client>("Client"); 
clientQuery = clientQuery.CreateAlias("Person", "p"); 

var primaryQuery = DetachedCriteria.For<Client>("Primary"); 
primaryQuery.SetProjection(Projections.Property("Primary.Id")); 
primaryQuery.Add(Restrictions.EqProperty("Client.PrimaryClient", "Primary.Id")); 
primaryQuery.CreateAlias("Person", "p"); 
primaryQuery.Add(Restrictions.Like("p.Surname", lastName, MatchMode.Start)); 

var secondaryQuery = DetachedCriteria.For<Client>(); 
secondaryQuery.SetProjection(Projections.Property("Id")); 
secondaryQuery.CreateCriteria("SecondaryClients") 
       .CreateCriteria("Person") 
       .Add(Restrictions.Like("Surname", lastName, MatchMode.Start)); 

clientQuery.Add(Restrictions.Disjunction() 
        .Add(Restrictions.Like("p.Surname", lastName, MatchMode.Start)) 
        .Add(Subqueries.Exists(primaryQuery)) 
        .Add(Subqueries.PropertyIn("Id", secondaryQuery))); 
0

我想你可以使用此查詢:

var result = _session.Linq<Client>.Where(client => client.Person.Name.StartsWith(lastName) || 
                client.PrimaryClient.Name.StartsWith(lastName) || 
                client.SecondaryClients.Any(sClient => sClient.Person.Name.StartsWith(lastName)));