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();
}