QueryOver集合包含所有值

时间:2014-01-14 15:01:40

标签: 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
}

我知道这有点令人费解,但由于我们通过将某些记录(如文档)放入与其所属的Program / Compartment(可互换术语)相对应的不同DB中而处理的安全性问题,因此模式存在。至。 MasterDocument,Program和DocumentCompartment的表位于“主”数据库中,该数据库包含所有隔离专区的信息,而几个不同的数据库将各自包含自己的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'方法,例如返回Session.Query()。Where(doc =&gt; 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语法进行相同的查询。不幸的是,我没有足够的知识或经验知道如何编写它。任何有关这方面的帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

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

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之间的比较在我评论的地方是否正确,但这应该让你开始朝着正确的方向前进。

一些注意事项:

  • 通常,您不能将QueryQver与LINQ语法一起使用。它们看起来很相似,但它们是不同的查询技术。
  • 有关QueryOver的基本介绍,请查看nhibernate.info上的this guide。不幸的是,这与官方文档方面的情况一样好。
  • 根据您提供的课程,假设您的映射有一些内容。