我想用nHibernate和QueryOver为List()创建一个通用方法。我已经达到了我想要添加连接的程度,但是如果没有指定我正在加入的泛型类型,我认为我不能这样做...这不会使它如此动态,因为必须声明每个泛型。有没有动态的连接列表?代码如下:
public static IList<T> QueryOver<T>(
Dictionary<Expression<Func<T, object>>, JoinType> joins,
List<Expression<Func<T, bool>>> predicates,
Dictionary<Expression<Func<T, object>>, System.Web.UI.WebControls.SortDirection> sortList,
int? maxResults
) where T : class
{
IList<T> results;
IQueryOver<T, T> query;
results = null;
// open the session
using (ISession session = OpenSession())
{
// begin a transaction
using (ITransaction transaction = session.BeginTransaction())
{
try
{
// declare the query
query = session.QueryOver<T>();
// joins
if (joins != null && joins.Count > 0)
{
foreach (KeyValuePair<Expression<Func<T, object>>, JoinType> join in joins)
{
// required to specify the type in the format query.JoinQueryOver<SubType>(join.Key, join.Value)
// BUT this means that it's not so dynamic because each SubType would have to be specified in the method call, yes?
query = query.JoinQueryOver(join.Key, join.Value);
}
}
// apply the where clauses
if (predicates != null && predicates.Count > 0)
{
foreach (Expression<Func<T, bool>> predicate in predicates)
{
query = query.Where(predicate);
}
}
// apply the sorting
if (sortList != null && sortList.Count > 0)
{
foreach (KeyValuePair<Expression<Func<T, object>>, System.Web.UI.WebControls.SortDirection> sort in sortList)
{
if (sort.Value == System.Web.UI.WebControls.SortDirection.Ascending)
{
query = query.OrderBy(sort.Key).Asc;
}
else
{
query = query.OrderBy(sort.Key).Desc;
}
}
}
// max results
if (maxResults.HasValue && maxResults.Value > 0)
{
query = (IQueryOver<T, T>)query.Take(maxResults.Value);
}
results = query.List();
// no errors, commit the transaction
transaction.Commit();
}
catch (Exception ex)
{
// error, rollback
transaction.Rollback();
// throw the exception and let the business logic deal with it
throw ex;
}
}
}
return results;
}
答案 0 :(得分:1)
使用JoinAlias代替JoinQueryOver ...这应该对你有用。
有两种类型的连接:类型T实体上的直接连接和间接连接(两个或多个步骤)。这些需要不同的方法。
(1)对于直接连接,您的方法可以接收IEnumerable类型(准备就绪):
Tuple<Expression<Func<T, object>>, Expression<Func<object>>>
其中一个示例在调用代码中可能如下所示:
JoiningEntity joiningEntity = null;
new Tuple<Expression<Func<YourEntityType, object>>, Expression<Func<object>>>(entity => entity.JoiningEntity, () => joiningEntity)
null对象只是一个别名,以便QueryOver可以解析它。您可能会对Visual Studio中的警告感到恼火,告诉您它是null,因此我将使用辅助方法来创建空对象,例如Null.Get<HolidayOccupancyPrice>()
(参见Null helper方法的底部)。
(2)对于间接连接,您需要传入一个IEnumerable类型:
Tuple<Expression<Func<object>>, Expression<Func<object>>>
即。如上所述,但没有实体类型。然后你的调用代码可能会发送这样的连接:
JoiningEntity joiningEntity = null;
new Tuple<Expression<Func<object>>, Expression<Func<object>>>(() => joiningEntity.IndirectJoiningEntity, () => joiningEntity)
将它放在你的查询方法中,你需要这样的东西:
IEnumerable<Tuple<Expression<Func<T, object>>, Expression<Func<object>>>> directJoins;
IEnumerable<Tuple<Expression<Func<object>>, Expression<Func<object>>>> indirectJoins;
// ....
foreach (var join in directJoins)
query = queryable.Left.JoinAlias(dependency.Item1, dependency.Item2);
foreach (var join in indirectJoins)
query = queryable.Left.JoinAlias(dependency.Item1, dependency.Item2);
(注意我明确指定了Left join - 如果你想要这个可控制的,你必须将它作为元组中的附加参数添加)
现在所有看起来都很复杂,但是一旦你把它放在一起就相当直接。您当然可以创建辅助方法来减少代码中“Func”的数量。
希望有所帮助!
空助手方法:
public static class Null
{
public static T Get<T>()
{
return default(T);
}
}