带有自定义投影和查询参数的 QueryOver
QueryOver With Custom Projection and Query Parameter
我在 class 中使用 属性 定义了一个查询,但我正在尝试使用 属性 构建一个相当复杂的查询并将 运行 放入NHibernate 告诉我它无法解析 属性: DueDate.
我的查询 class 如下所示:
public class SomeQuery {
public DateTime DueDate { get; private set; }
public SomeQuery(DateTime dueDate) {
DueDate = dueDate;
}
public QueryOver GetQueryOver() {
PrimaryObject po = null;
SubObject so = null;
return QueryOver.Of<PrimaryObject>(() => po)
.JoinAlias(() => so.SubObjects, () => so)
.Where(
Restrictions.Le(
DateProjections.DateDiff("d", () so.Value, () = DueDate),
0
)
);
}
}
我已经完全按照 Andrew Whitaker 的博客 QueryOver Series - Part 7: Using SQL Functions
中的描述实现了 DateProjections Class
PrimaryObject
和 SubObject
的内容对于示例来说并不重要,除了以下内容:
public class PrimaryObject {
public virtual Guid Id { get; set; }
public List<SubObject> Implementations { get; set; }
}
public class SubObject {
public virtual Guid Id { get; set; }
public virtual string Value { get; set; }
}
对于映射,您可以假设这些字段以合理的方式映射到数据库,因为我觉得这不是问题所在。
当我尝试在测试中使用此查询时,如下所示:
var testDate = new DateTime(2015, 06, 01);
IEnumerable<PrimaryObject> result = repository.FindAll(new SomeQuery(testDate));
我得到一个 NHibernate.QueryException
:
NHibernate.QueryException : could not resolve property: DueDate of: PrimaryObject
很明显,我有一个未映射的 属性,这导致投影有胃灼热感。
正在寻找一个最小的仪式解决方案来映射 DueDate。 我看过 Andrew 在 QueryOver Series - Part 9: Extending QueryOver to Use Custom Methods and Properties 中的示例,但感觉像是很多仪式。
我也 google 寻求解决方案,但我的 google foo 失败了..
建议?解决方案?
博客上的 DateDiff
实现假设您希望计算数据库字段之间的差异。这不是您想要的:您想将一个数据库字段与一个常量进行比较。
您必须重构 DateProjections
方法集以允许您将常量作为参数传递:
public static class DateProjections
{
private const string DateDiffFormat = "datediff({0}, ?1, ?2)";
// Here's the overload you need
public static IProjection DateDiff
(
string datepart,
Expression<Func<object>> startDate,
DateTime endDate
)
{
return DateDiff(
datePart,
Projections.Property(startDate),
Projections.Constant(endDate)
);
}
// Keeping Andrew Whitaker's original signature
public static IProjection DateDiff
(
string datepart,
Expression<Func<object>> startDate,
Expression<Func<object>> endDate
)
{
return DateDiff(
datePart,
Projections.Property(startDate),
Projections.Property(endDate)
);
}
// Added a function that's shared by
// all of the overloads
public static IProjection DateDiff(
string datepart,
IProjection startDate,
IProjection endDate)
{
// Build the function template based on the date part.
string functionTemplate = string.Format(DateDiffFormat, datepart);
return Projections.SqlFunction(
new SQLFunctionTemplate(NHibernateUtil.Int32, functionTemplate),
NHibernateUtil.Int32,
startDate,
endDate);
}
}
现在您可以像这样调用它了:
public QueryOver GetQueryOver() {
PrimaryObject po = null;
SubObject so = null;
return QueryOver.Of<PrimaryObject>(() => po)
.JoinAlias(() => so.SubObjects, () => so)
.Where(
Restrictions.Le(
DateProjections.DateDiff("d", () => so.Value, DueDate),
0
)
);
}
我在 class 中使用 属性 定义了一个查询,但我正在尝试使用 属性 构建一个相当复杂的查询并将 运行 放入NHibernate 告诉我它无法解析 属性: DueDate.
我的查询 class 如下所示:
public class SomeQuery {
public DateTime DueDate { get; private set; }
public SomeQuery(DateTime dueDate) {
DueDate = dueDate;
}
public QueryOver GetQueryOver() {
PrimaryObject po = null;
SubObject so = null;
return QueryOver.Of<PrimaryObject>(() => po)
.JoinAlias(() => so.SubObjects, () => so)
.Where(
Restrictions.Le(
DateProjections.DateDiff("d", () so.Value, () = DueDate),
0
)
);
}
}
我已经完全按照 Andrew Whitaker 的博客 QueryOver Series - Part 7: Using SQL Functions
中的描述实现了 DateProjections ClassPrimaryObject
和 SubObject
的内容对于示例来说并不重要,除了以下内容:
public class PrimaryObject {
public virtual Guid Id { get; set; }
public List<SubObject> Implementations { get; set; }
}
public class SubObject {
public virtual Guid Id { get; set; }
public virtual string Value { get; set; }
}
对于映射,您可以假设这些字段以合理的方式映射到数据库,因为我觉得这不是问题所在。
当我尝试在测试中使用此查询时,如下所示:
var testDate = new DateTime(2015, 06, 01);
IEnumerable<PrimaryObject> result = repository.FindAll(new SomeQuery(testDate));
我得到一个 NHibernate.QueryException
:
NHibernate.QueryException : could not resolve property: DueDate of: PrimaryObject
很明显,我有一个未映射的 属性,这导致投影有胃灼热感。
正在寻找一个最小的仪式解决方案来映射 DueDate。 我看过 Andrew 在 QueryOver Series - Part 9: Extending QueryOver to Use Custom Methods and Properties 中的示例,但感觉像是很多仪式。
我也 google 寻求解决方案,但我的 google foo 失败了..
建议?解决方案?
博客上的 DateDiff
实现假设您希望计算数据库字段之间的差异。这不是您想要的:您想将一个数据库字段与一个常量进行比较。
您必须重构 DateProjections
方法集以允许您将常量作为参数传递:
public static class DateProjections
{
private const string DateDiffFormat = "datediff({0}, ?1, ?2)";
// Here's the overload you need
public static IProjection DateDiff
(
string datepart,
Expression<Func<object>> startDate,
DateTime endDate
)
{
return DateDiff(
datePart,
Projections.Property(startDate),
Projections.Constant(endDate)
);
}
// Keeping Andrew Whitaker's original signature
public static IProjection DateDiff
(
string datepart,
Expression<Func<object>> startDate,
Expression<Func<object>> endDate
)
{
return DateDiff(
datePart,
Projections.Property(startDate),
Projections.Property(endDate)
);
}
// Added a function that's shared by
// all of the overloads
public static IProjection DateDiff(
string datepart,
IProjection startDate,
IProjection endDate)
{
// Build the function template based on the date part.
string functionTemplate = string.Format(DateDiffFormat, datepart);
return Projections.SqlFunction(
new SQLFunctionTemplate(NHibernateUtil.Int32, functionTemplate),
NHibernateUtil.Int32,
startDate,
endDate);
}
}
现在您可以像这样调用它了:
public QueryOver GetQueryOver() {
PrimaryObject po = null;
SubObject so = null;
return QueryOver.Of<PrimaryObject>(() => po)
.JoinAlias(() => so.SubObjects, () => so)
.Where(
Restrictions.Le(
DateProjections.DateDiff("d", () => so.Value, DueDate),
0
)
);
}