我正在开发一个小型项目,该项目应该允许对数据库进行基本搜索。 目前我正在使用nhibernate进行数据库交互。 在数据库中,我有2个表:人员和地址。 Person表与Address具有多对一关系。
我提出的搜索代码是:
public IList<T> GetByParameterList(List<QueryParameter> parameterList)
{
if (parameterList == null)
{
return GetAll();
}
using (ISession session = NHibernateHelper.OpenSession())
{
ICriteria criteria = session.CreateCriteria<T>();
foreach (QueryParameter param in parameterList)
{
switch (param.Constraint)
{
case ConstraintType.Less:
criteria.Add(Expression.Lt(param.ParameterName, param.ParameterValue));
break;
case ConstraintType.More:
criteria.Add(Expression.Gt(param.ParameterName, param.ParameterValue));
break;
case ConstraintType.LessOrEqual:
criteria.Add(Expression.Le(param.ParameterName, param.ParameterValue));
break;
case ConstraintType.EqualOrMore:
criteria.Add(Expression.Ge(param.ParameterName, param.ParameterValue));
break;
case ConstraintType.Equals:
criteria.Add(Expression.Eq(param.ParameterName, param.ParameterValue));
break;
case ConstraintType.Like:
criteria.Add(Expression.Like(param.ParameterName, param.ParameterValue));
break;
}
}
try
{
IList<T> result = criteria.List<T>();
return result;
}
catch
{
//TODO: Implement some exception handling
throw;
}
}
}
查询参数是一个帮助对象,我用它来创建标准并将其发送到dal,它看起来像这样:
public class QueryParameter
{
public QueryParameter(string ParameterName, Object ParameterValue, ConstraintType constraintType)
{
this.ParameterName = ParameterName;
this.ParameterValue = ParameterValue;
this.Constraint = constraintType;
}
public string ParameterName
{
get;
set;
}
public Object ParameterValue
{
get;
set;
}
public ConstraintType Constraint
{
get;
set;
}
}
现在,如果我正在进行像FirstName =“John”这样的搜索,这种情况很有效,但是当我尝试给出像Street =“Some Street”这样的参数时,这种效果并不好。似乎nhibernate正在Person表中寻找街道列而不是在Address表中。
我应该如何更改代码,以便我可以进行正确的搜索?提示?也许有一些替代方案?
免责声明:我有点像菜鸟,所以请温柔;) 谢谢,丹尼斯。
答案 0 :(得分:1)
我会为每个域对象类做一个强类型搜索类(例如,使用针对我的域对象的代码生成)。
我会有一个抽象类,使用非常接近当前代码的东西放置ICriteriaBuilder
逻辑,然后对任何内部ICriteriaBuilder属性进行递归。
我会有类似伪代码的东西:
class SearchCriteriaBuilder
public ConstraintType constraintType
public ICriteria Build(ISearchCriteriaBuilder pSearchCriteria)
{'your code goes there'}
class AdressSearchCriteriaBuilder : SearchCriteriaBuilder
public StringSearchCriteriaBuilder street;
public IntegerSearchCriteriaBuilder number;
class PersonSearchCriteriaBuilder : SearchCriteriaBuilder
public StringSearchCriteriaBuilder name;
public AdressSearchCriteriaBuilder adress;
答案 1 :(得分:0)
您可以像这样使用hql查询
from Person p join Address a where a.Street = :street
并使用查询设置:street参数。
我发现使用hql比处理标准内容要容易得多,尤其是当你是新手时。你的第一直觉是标准化你的nhibernate用法,但是当你学习它时,最好让你的代码接近nhibernate API而不是编写太多辅助方法。
答案 2 :(得分:0)
正在寻找Person实体中的Street属性(注意ORM语言......没有表和列;-))因为这一行:
ICriteria criteria = session.CreateCriteria<T>();
我假设您的类型T
是Person,因此您的条件假定您添加的约束引用Person中的属性。
如果您传入的参数是地址实体上的过滤器,则需要调用CreateAlias(...)
以“加入”地址。
答案 3 :(得分:0)
请在1:57查看此视频:http://skillsmatter.com/podcast/open-source-dot-net/nhibernate-tutorial-by-ayende-rahien
Ayende(最着名的nhibernate专家)告诉你如何使用标准api构建动态查询。请注意2:04:30发布的foreach解释