C# NHibernate QueryByExample仅包括某些属性
我已经创建了一个自定义属性选择器来接受构造函数中的数组,以说明搜索中应该包含哪些属性。只要没有组件类型,这种方法就可以很好地工作,但是我该如何处理这些组件类型呢?以下是一个例子:C# NHibernate QueryByExample仅包括某些属性,c#,nhibernate,query-by-example,C#,Nhibernate,Query By Example,我已经创建了一个自定义属性选择器来接受构造函数中的数组,以说明搜索中应该包含哪些属性。只要没有组件类型,这种方法就可以很好地工作,但是我该如何处理这些组件类型呢?以下是一个例子: public class Customer { public virtual int Id { get; private set; } public virtual Name Name { get; set; } public virtual bool isPreferred { get; se
public class Customer
{
public virtual int Id { get; private set; }
public virtual Name Name { get; set; }
public virtual bool isPreferred { get; set; }
//...etc
}
public class Name
{
public string Title { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Fullname { get; }
}
public class CustomerPropertySelector : Example.IPropertySelector
{
private string[] _propertiesToInclude = { };
public CustomerPropertySelector(string[] propertiesToInclude)
{
this._propertiesToInclude = propertiesToInclude;
}
public bool Include(object propertyValue, String propertyName, NHibernate.Type.IType type)
{
//...Checking for null and zeros etc, excluded for brevity
if (!_propertiesToInclude.Contains(propertyName))
return false;
return true;
}
}
我想能够搜索的名字,但不一定最后。但是属性名是name,所以名字和姓氏似乎都是同一属性的一部分,类似于name.Firstname,通常作为标准,在这里似乎不起作用。最好的解决办法是什么
示例:
Customer exampleCust = new Customer(FirstName: "Owen");
IList<Customer> matchedCustomers = _custRepo.GetByExample(exampleCust, new string[] { "Name.FirstName" });
我不确定确定确定属性是否为组件类的最佳方法,欢迎提供任何关于如何改进代码的建议。以下代码将替换您用于填充属性的逻辑。我把它从一个数组改为一个列表,这样我就可以使用Add方法了,因为我很懒,但我想你明白了。这仅适用于一个子级别的属性。对于n个级别,您需要递归
List<string> _propertiesToInclude = new List<string>();
Type t;
var props = t.GetProperties();
foreach (var prop in props)
{
if (prop.PropertyType.IsClass)
foreach (var subprop in prop.PropertyType.GetProperties())
_propertiesToInclude.Add(string.Format("{0}.{1}", prop.Name, subprop.Name));
else
_propertiesToInclude.Add(prop.Name);
}
List\u propertiesToInclude=newlist();
t型;
var props=t.GetProperties();
foreach(道具中的var道具)
{
if(prop.PropertyType.IsClass)
foreach(prop.PropertyType.GetProperties()中的变量subop)
_propertiesToInclude.Add(string.Format(“{0}.{1}”,prop.Name,subop.Name));
其他的
_propertiesToInclude.Add(属性名称);
}
我以为我有什么想法,但再次阅读您的问题时,您想知道为什么QBE NHibernate代码不适用于组件属性
[Test]
public void TestExcludingQBE()
{
using (ISession s = OpenSession())
using (ITransaction t = s.BeginTransaction())
{
Componentizable master = GetMaster("hibernate", null, "ope%");
ICriteria crit = s.CreateCriteria(typeof(Componentizable));
Example ex = Example.Create(master).EnableLike()
.ExcludeProperty("Component.SubComponent");
crit.Add(ex);
IList result = crit.List();
Assert.IsNotNull(result);
Assert.AreEqual(3, result.Count);
master = GetMaster("hibernate", "ORM tool", "fake stuff");
crit = s.CreateCriteria(typeof(Componentizable));
ex = Example.Create(master).EnableLike()
.ExcludeProperty("Component.SubComponent.SubName1");
crit.Add(ex);
result = crit.List();
Assert.IsNotNull(result);
Assert.AreEqual(1, result.Count);
t.Commit();
}
}
我认为您需要为名称部分创建子条件查询
也许是这样的:
public IList<Customer> GetByExample(Customer customer, string[] propertiesToExclude){
Example customerQuery = Example.Create(customer);
Criteria nameCriteria = customerQuery.CreateCriteria<Name>();
nameCriteria.Add(Example.create(customer.Name));
propertiesToExclude.ForEach(x=> customerQuery.ExcludeProperty(x));
propertiesToExclude.ForEach(x=> nameCriteria.ExcludeProperty(x));
return customerQuery.list();
}
我想你对这个问题有点误解了-问题不在于决定如何填充
\u properties包括,而是给定了数组如何告诉QBE我想从比较中排除Name.LastName
,而不是Name.FirstName
。我认为这可能是不可能的,因为就QBE而言,Name
是一个整体,我可以包含也可以不包含,但不能部分包含。因此,您需要CustomerPropertySelector.include(null,“Name.FirstName”,IType.Something)
返回true
和CustomerPropertySelector.Include(null,“Name.LastName”,IType.Something)
返回false
?基于什么标准?难道你不能硬编码方法以排除Name.LastName吗?我想我一定是漏掉了重点。我也这么认为,也许我没有正确地回答这个问题。我想创建一个示例customernew customer(FirstName:“Owen”)
,然后用propertiesToInclude:new string[]{“Name.FirstName”}
将其传递给我的方法,然后该方法将只基于该字段比较对象。typeof(string).IsClass
返回true,所以这在具有字符串属性的类上不起作用。我想没有比循环检查所有基本类型更好的方法了。我认为你用“QBE NHibernate代码不能处理组件属性”一针见血。是否有一个引用可以证实这一点?问题是QBE不知道是否包括/排除对象的组件部分,除非您专门将组件条件添加到查询中。我已经完全放弃在应用程序中使用QBE,转而使用以下API(按优先顺序)。Linq,QueryOver,Criteria,HQL。在我的最后一条评论之后,我在NHibernate测试项目中发现了一些代码,这些代码显示了如何从QBE查询中排除组件属性。啊哈!非常感谢您的跟进,这让我意识到了答案。QBE确实支持组件属性,我只是对如何做感到困惑。不幸的是,therealmitchconnors的答案更接近事实,尽管没有NHTest的例子,我永远也不会明白这一点。
[Test]
public void TestExcludingQBE()
{
using (ISession s = OpenSession())
using (ITransaction t = s.BeginTransaction())
{
Componentizable master = GetMaster("hibernate", null, "ope%");
ICriteria crit = s.CreateCriteria(typeof(Componentizable));
Example ex = Example.Create(master).EnableLike()
.ExcludeProperty("Component.SubComponent");
crit.Add(ex);
IList result = crit.List();
Assert.IsNotNull(result);
Assert.AreEqual(3, result.Count);
master = GetMaster("hibernate", "ORM tool", "fake stuff");
crit = s.CreateCriteria(typeof(Componentizable));
ex = Example.Create(master).EnableLike()
.ExcludeProperty("Component.SubComponent.SubName1");
crit.Add(ex);
result = crit.List();
Assert.IsNotNull(result);
Assert.AreEqual(1, result.Count);
t.Commit();
}
}