查询多个实体

时间:2011-11-01 20:26:17

标签: c# nhibernate nhibernate-criteria

我有一个奇怪的要求我不确定如何解决。

假设以下类定义:

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的别名做些什么。我在这里走错了路吗?任何帮助将不胜感激。

注意:我原本忘了提。 SecondaryClients和PrimaryClient可能为空。

2 个答案:

答案 0 :(得分: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)));

答案 1 :(得分: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)));