-2

让我们以这些域对象为例:

public class A 
{
    public Guid Id { get; set; }
    public ICollection<B> CollectionOfB { get; set; }
}

public class B 
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

我需要使用 NHibernate 3.x检索具有这些名称的任何A对象Bname1name2

例如,假设您B从名称数组中获取要检索的字符串作为字符串string[] names = new string[] { "name1", "name2" }

我想过.Query<A>().Where(someA => some.CollectionOfB.Any(someB => names.Contains(someB.Name)))我怀疑这会被 NHibernate LINQ 提供程序编译为 SQL 查询。也许这会被编译成一个不是很优化的 SQL 查询。

使用 NHibernate 3.x LINQ 提供程序构建此查询的最佳方式是什么?

4

2 回答 2

2

你想到的查询:

var someAs = session.Query<A>().Where(someA => some.CollectionOfB.Any(someB => names.Contains(someB.Name)));

工作正常,我在类似的结构上对其进行了测试。NHibernate 发出一个包含 IN 子句的相关子查询。

[编辑]关于您的评论,从代码中可以清楚查询的意图的意义上说,这是最佳的。必须测量性能,并且数据库引擎使用查询优化器,该优化器通常可以将丑陋的查询转换为非常有效的查询,因此,像许多事情一样,您无法判断查询的外观。

我将示例查询更改为使用内部联接并获得了更好的执行计划(它消除了排序操作)。如果我使用 LINQ 查询语法重新编写查询,它会使用更好的执行计划,但查询不包含内部联接;相反,它在 where 子句中使用旧式连接。

var someAs = (from someA in session.Query<A>()
              join someB in session.Query<B>() on someA.Id equals someB.A_Id
              where names.Contains(someB.Name)
              select someA).ToArray();
于 2013-01-07T15:03:54.247 回答
0

如果您扩展 B 类以引用 A:

public class B 
{
    public A A {get;set;}
    public Guid Id { get; set; }
    public string Name { get; set; }
}

然后像这样做子查询:

var aObjectsToRetrieve = Query<B>().Where(x=>x.Name.StartsWith("name1")).Select(x=>x.A.Id);

然后在 A 的查询中应用 Exists() 以获取您需要的 A 对象。如果您有一组名称,您可以尝试这样的事情(或根据您的情况使用连词):

  var disjunction = new Disjunction();
  var names = new[] {"name1", "name2"};
  foreach (string name in names)
            disjunction.Add(Restrictions.InsensitiveLike(PropName<User>(x => x.Name), name));
于 2013-01-07T12:32:59.310 回答