I am having trouble working out how to get the following sql into an NHibernate ICriteria:
select * from Contract contract_outer
where exists (
select 1 from RequiredDocRules
where not exists (
select 1 from Contract contract_inner
inner join ContractDocs contractDocs on cDocs.ContractId = c_inner.Id
inner join Doc doc doc.Id = contractDocs.DocId
where contract_inner.Id = contract_outer.Id
and doc.Type = RequiredDocRules.DocType)
)
and RequiredDocRules.ContractType = contract_outer.Type
)
Basically, the query is saying "Show me contracts that are missing required documents, based on the rules for this type of contract".
The CreateCriteria looks like this:
var subqueryB = DetachedCriteria.For<Contract>("contract_inner")
.CreateAlias("contract_inner.Docs", "doc")
.Add(Restrictions.EqProperty("doc.Type", "rule.DocType"))
.Add(Restrictions.EqProperty("contract_inner.Id", "contract_outer.Id")
.SetProjection(Projections.Id());
var subqueryA = DetachedCriteria.For<RequiredDocRule>("rule")
.Add(Restriction.EqProperty("rule.ContractType", "contract_outer.Type"))
.Add(Subqueries.NotExists(subqueryB))
.SetProjection(Projections.Id());
return Session.CreateCriteria<Contract>("contract_outer")
.Add(Subqueries.Exists(subqueryA))
.List<Contract>();
This above code throws the following obscure exception:
Could not find a matching criteria info provider to: contract_inner.Id = contract_outer.Id and doc.Type = rule.DocType
I've narrowed the issue down to the "contract_inner.Id = contract_outer.Id" restriction. Maybe it is having trouble traversing up through two layers of subqueries?
I am using NHibernate 2.1 btw.
I seem to be the only person getting this exception - if you google for the exception message another one of my Stackoverflow posts comes up number one. This question is similar, but different. So frustrating!