Nhibernate Linq 按名称而不是按 Id 获取 <T> 对象
Nhibernate Linq Get<T> object by name not by Id
public T FindById(object id)
{
return session.Get<T>(id);
}
我想通过名称获取对象
类似这样,但我无法编写 T
类型的查询
session.Get<T>().Where(x => x.something == something).SingleOrDefault();
或者是否有其他替代方法?
您必须将 T 限制为具有特定 属性 的内容。例如,您可以创建一个名为 NamedObject 的超类,它有一个 属性 Name 并使所有可命名对象都继承自它。将 T 限制为 NameableObject 或后代将允许您在查询中访问名称 属性。
不是特别优雅,但应该可以。
您可以使用 Expression
树并构建如下内容:
protected T Get<T, TValue>(string propertyName, TValue value) where T : class
{
var par = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
var eq = System.Linq.Expressions.Expression.Equal(System.Linq.Expressions.Expression.Property(par, propertyName), System.Linq.Expressions.Expression.Constant(value));
var lambda = System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(eq, par);
return session.QueryOver<T>().Where(lambda).SingleOrDefault();
}
请注意,我使用的是完整的命名空间 + class 名称,因为 NHibernate 有另一个 Expression
class.
我认为你应该使用反射来查询泛型类型,就像这样:
session.Get<T>().Where(P => typeof(P).GetPropery("PropertyName").GetValue(P).ToString() == "Something").SingleOrDefault();
在这段代码中,typeof(oObject)
returnsde一个Type
对象的实例,然后GetProperty("PropertyName")
方法returns你一个System.Reflection.PropertyInfo
这样你就可以通过 GetValue(P)
方法获得 属性 值,该方法接收包含 属性 的对象实例,在这种情况下是 [P] 在 Lamba 表达式中创建。
NHiberante 中有一个原生解决方案:
Chapter 15. Criteria Queries
这个条件 API (从一开始就有) 正是我们在这里所需要的。例如 QueryOver
API - 建立在其之上。
最大的好处是,它确实可以与 "strings" 一起工作。这将是非常简单,易于维护的一段代码:
public T GetByProperty<T>(string propertyName, object value)
where T: class
{
var session = ... // get a session
return session.CreateCriteria<T>()
.Add(Restrictions.Eq(propertyName, value))
.SetMaxResults(1)
.List<T>()
.FirstOrDefault();
}
有完整的doc
我不确定您所说的 "I am not able to write a query with type T" 是什么意思。
但是你可以调用支持重构的表达式。
public T GetByExpression<T>(Expression<Func<T, bool>> restriction) where T : class
{
return Session.QueryOver<T>().Where(restriction).SingleOrDefault();
}
public T FindById(object id)
{
return session.Get<T>(id);
}
我想通过名称获取对象
类似这样,但我无法编写 T
session.Get<T>().Where(x => x.something == something).SingleOrDefault();
或者是否有其他替代方法?
您必须将 T 限制为具有特定 属性 的内容。例如,您可以创建一个名为 NamedObject 的超类,它有一个 属性 Name 并使所有可命名对象都继承自它。将 T 限制为 NameableObject 或后代将允许您在查询中访问名称 属性。
不是特别优雅,但应该可以。
您可以使用 Expression
树并构建如下内容:
protected T Get<T, TValue>(string propertyName, TValue value) where T : class
{
var par = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
var eq = System.Linq.Expressions.Expression.Equal(System.Linq.Expressions.Expression.Property(par, propertyName), System.Linq.Expressions.Expression.Constant(value));
var lambda = System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(eq, par);
return session.QueryOver<T>().Where(lambda).SingleOrDefault();
}
请注意,我使用的是完整的命名空间 + class 名称,因为 NHibernate 有另一个 Expression
class.
我认为你应该使用反射来查询泛型类型,就像这样:
session.Get<T>().Where(P => typeof(P).GetPropery("PropertyName").GetValue(P).ToString() == "Something").SingleOrDefault();
在这段代码中,typeof(oObject)
returnsde一个Type
对象的实例,然后GetProperty("PropertyName")
方法returns你一个System.Reflection.PropertyInfo
这样你就可以通过 GetValue(P)
方法获得 属性 值,该方法接收包含 属性 的对象实例,在这种情况下是 [P] 在 Lamba 表达式中创建。
NHiberante 中有一个原生解决方案:
Chapter 15. Criteria Queries
这个条件 API (从一开始就有) 正是我们在这里所需要的。例如 QueryOver
API - 建立在其之上。
最大的好处是,它确实可以与 "strings" 一起工作。这将是非常简单,易于维护的一段代码:
public T GetByProperty<T>(string propertyName, object value)
where T: class
{
var session = ... // get a session
return session.CreateCriteria<T>()
.Add(Restrictions.Eq(propertyName, value))
.SetMaxResults(1)
.List<T>()
.FirstOrDefault();
}
有完整的doc
我不确定您所说的 "I am not able to write a query with type T" 是什么意思。 但是你可以调用支持重构的表达式。
public T GetByExpression<T>(Expression<Func<T, bool>> restriction) where T : class
{
return Session.QueryOver<T>().Where(restriction).SingleOrDefault();
}