c# - QueryOver 集合包含所有值

标签 c# nhibernate queryover

简化域:

public class MasterDocument {
    Guid ID;
    Program StorageCompartment;
    ISet<DocumentCompartment> Compartments;
}
public class Program {
    int ID;
    string GroupName;
}
public class DocumentCompartment {
    int ID;
    Program AssociatedCompartment;
    MasterDocument AssociatedDocument;
}
public class Document {
    Guid ID;
    MasterDocument MasterDocument;
    //Many more properties
}

我知道这有点令人费解,但由于我们通过将某些记录(如文档)放入与它们所属的程序/隔间(可互换术语)相对应的不同数据库来处理安全问题,所以模式是这样存在的到。 MasterDocument、Program 和 DocumentCompartment 的表位于“master”数据库中,该数据库包含所有隔间的信息,而几个不同的数据库将各自包含自己的 Documents 表。无论如何,关于问题:

我正在尝试构建一个查询,通过该查询向我传递一个组名列表,并且我只想要没有关联的隔间的文档,这些隔间不包含在该组名列表中。

举个例子:
Doc1 与隔间 P1 关联
Doc2与P2、P3、P7相关联
Doc3 与 P1 和 P3 关联
我想检查以下组:P1、P3、P4、P7(这些是我有权访问的组)

我应该取回 Doc1 和 Doc3,因为我没有 P2 的权限,而 Doc2 需要权限。我能够通过以下查询使用 LINQ 提供程序执行此操作:

string[] groups = new[] { "P1", "P3", "P4", "P7" };
return Session.Query<Document>().Where(doc => doc.MasterDocument.Compartments.All(comp => groups.Contains(comp.AssociatedCompartment.GroupName));

(还有关于上面的注释:如果我尝试将该逻辑封装在 Document 类中并将该方法传递给“Where”方法,例如 return Session.Query().Where(doc => doc.CanAccess(组)),然后我得到一个 System.NotSupportedException。我有点理解为什么,但如果有解决方法,那就太好了。)

生成的 SQL 看起来像这样:

exec sp_executesql 
N'select
doc.DocumentGuid as guid
from Documents doc 
where  not (exists 
(select comp.DocumentCompartmentID 
 from Master.MasterDocuments master, 
      Master.DocumentCompartments comp, 
      Master.Programs prog 
 where doc.DocumentGuid=master.DocumentGuid and 
       master.DocumentGuid=comp.DocumentGuid and 
       comp.CompartmentID=prog.ProgramID and  
       not (prog.ADGroupName in ('P1', 'P3', 'P4', 'P7'))
 ))',

我现在正试图找出如何使用 NHibernate QueryOver 语法执行相同的查询。不幸的是,我没有足够的知识或经验来知道如何编写它。对此的任何帮助将不胜感激!

最佳答案

我相信你想要这样的东西:

IList<Guid> results = Session.QueryOver<Document>(() => documentAlias)
    .WithSubquery.WhereNotExists(
        QueryOver.Of<MasterDocument>()
                .Where(md => md.ID == documentAlias.MasterDocument.ID) // Not sure about this
            .JoinQueryOver(md => md.Compartments)
            .JoinQueryOver(cmp => cmp.AssociatedCompartment)
                .WhereNot(acmp => acmp.GroupName.IsIn(new[] { "P1", "P3", "P4", "P7" })))
    .Select(doc => doc.ID)
    .List<Guid>();

我不确定 MasterDocument.IDDocument.MasterDocument.ID 之间的比较在我评论的地方是否正确,但这应该让你开始正确的方向。

一些注意事项:

  • 一般来说,您不能将 LINQ 语法与 QueryOver 一起使用。它们看起来很相似,但它们是不同的查询技术。
  • 有关 QueryOver 的基本介绍,请查看 this guide在 nhibernate.info 上。不幸的是,就官方文档而言,这与您所能获得的一样好
  • 这根据您提供的类假设了一些关于您的映射的事情。

关于c# - QueryOver 集合包含所有值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21116726/

相关文章:

c#,使用 Nhibernate(QueryOver 或 Linq)预先加载集合集合返回 "cannot simultaneously fetch multiple bags"

NHibernate 在 QueryOver 中检查相同的连接

c# - 重启按钮在 Unity 5.6 上不起作用

c# - #DEBUG ASPX 页面中的预处理器语句

c# - 如何强制 EF-Code First 忽略创建现有 View ?

c# - 为什么 ReferenceEquals 和 == 运算符的行为与 Equals 不同

c# - 使用哪个ORM?

c# - NHibernate 级联删除

缺少映射时 nhibernate QueryOver 不抛出异常

C# 字符串测量