ICriteria,添加对集合内容的限制
使用 NHibernate 我试图获取 B 的列表,其中 B 的 IList 属性包含 A 的特定实例。
以下代码有望更清楚地解释这种情况:
public void test()
{
A a1 = new A();
A a2 = new A();
B b1 = new B();
b1.As = new List<A> { a1 };
// ...database save cut...
using (ISession session = SessionFactory.OpenSession())
{
var result1 = session.CreateCriteria<B>()
.CreateAlias("As", "a_As")
.Add(Restrictions.Eq("a_As.ID", a1.ID))
.List();
var result2 = session.CreateCriteria<B>()
.CreateAlias("As", "a_As")
.Add(Restrictions.Eq("a_As", a1))
.List();
}
}
class A
{
public virtual int ID { get; set; }
}
class B
{
public virtual IList<A> As { get;set;}
}
第二个查询失败并出现错误:could not解析属性:a_As of:B
如何使用对象实例执行此查询,而不像上面的第一个查询那样显式使用 ID 属性。
编辑: 为了扩展这一点,我有一个通用类,它对我的实体执行 NHibernate 操作。我刚刚创建了一个“IsReferenced”方法,其开头如下:
public bool IsReferenced(T entity)
{
// Get the types (and their properties) that reference the type in question
var typeProps = from type in typeof(T).Assembly.GetTypes()
let props = type.GetProperties().Where(p => p.PropertyType == typeof(T)).Select(p => p.Name)
let collections = type.GetProperties().Where(p => typeof(IEnumerable<T>).IsAssignableFrom(p.PropertyType)).Select(p => p.Name)
where type.IsClass && !type.IsAbstract && ((props != null && props.Count() > 0) || (collections != null && collections.Count() > 0))
select new { EntityType = type, Properties = props, Collections = collections };
var multiCriteria = NHibernateSession.CreateMultiCriteria();
foreach (var typeProp in typeProps)
{
var criteria = NHibernateSession.CreateCriteria(typeProp.EntityType);
var disjunction = new Disjunction();
foreach (var propName in typeProp.Properties)
{
disjunction.Add(Restrictions.Eq(propName, entity));
}
foreach (var collectionName in typeProp.Collections)
{
throw new NotImplementedException();
}
criteria.Add(disjunction);
multiCriteria.Add(criteria);
}
.....
}
我使用 typeProps 构建 MultiCriteria 来查找引用指定实体的任何实体。它对于普通属性工作得很好,但集合属性却让我感到悲伤。我不知道如何将限制添加到标准中。
Using NHibernate I'm trying to get obtain a list of B's where an IList property of B contains a specific instance of A.
The following code should hopefully explain the situation more clearly:
public void test()
{
A a1 = new A();
A a2 = new A();
B b1 = new B();
b1.As = new List<A> { a1 };
// ...database save cut...
using (ISession session = SessionFactory.OpenSession())
{
var result1 = session.CreateCriteria<B>()
.CreateAlias("As", "a_As")
.Add(Restrictions.Eq("a_As.ID", a1.ID))
.List();
var result2 = session.CreateCriteria<B>()
.CreateAlias("As", "a_As")
.Add(Restrictions.Eq("a_As", a1))
.List();
}
}
class A
{
public virtual int ID { get; set; }
}
class B
{
public virtual IList<A> As { get;set;}
}
The second query fails with the error: could not resolve property: a_As of: B
How can I perform this query using object instances without explicitly using the ID properties like in the first query above.
Edit:
To expand on this, I have a generic class which performs NHibernate operations with my entities. I've just created an "IsReferenced" method that begins as follows:
public bool IsReferenced(T entity)
{
// Get the types (and their properties) that reference the type in question
var typeProps = from type in typeof(T).Assembly.GetTypes()
let props = type.GetProperties().Where(p => p.PropertyType == typeof(T)).Select(p => p.Name)
let collections = type.GetProperties().Where(p => typeof(IEnumerable<T>).IsAssignableFrom(p.PropertyType)).Select(p => p.Name)
where type.IsClass && !type.IsAbstract && ((props != null && props.Count() > 0) || (collections != null && collections.Count() > 0))
select new { EntityType = type, Properties = props, Collections = collections };
var multiCriteria = NHibernateSession.CreateMultiCriteria();
foreach (var typeProp in typeProps)
{
var criteria = NHibernateSession.CreateCriteria(typeProp.EntityType);
var disjunction = new Disjunction();
foreach (var propName in typeProp.Properties)
{
disjunction.Add(Restrictions.Eq(propName, entity));
}
foreach (var collectionName in typeProp.Collections)
{
throw new NotImplementedException();
}
criteria.Add(disjunction);
multiCriteria.Add(criteria);
}
.....
}
I'm using typeProps to build a MultiCriteria to find any entities anywhere that reference the one specified. It works fine for normal properties, but collection properties are giving me grief. I'm not sure how to go about adding the restriction into the criteria.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
HQL 比 Criteria 更好地服务于这种类型的查询:
This type of query is better served by HQL than Criteria:
我找到了一个似乎适用于我当前所有实体的解决方案,基于我在处理此问题时浏览过的两条信息:
object ISession.GetIdentifier(object obj)
这两个花絮让我们可以做这样的事情:
结果 IsReferenced 方法看起来像这样:
如果我的大脑在我提出之前就已经启动了就好了我的声誉的一半作为赏金......
I've found a solution that appears to work for all of my current entities, based on two pieces of information I've skimmed over whilst working on this:
object ISession.GetIdentifier(object obj)
These two titbits let us do something like this:
And the resulting IsReferenced method looks like this:
If only my brain had kicked in before I put up half of my reputation as a bounty...