我已经在一个带有属性的类中定义了一个查询,但我正在尝试使用该属性构建一个相当复杂的查询并且遇到NHibernate告诉我它无法解析属性:DueDate。
My Query类如下所示:
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类 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; }
}
对于Mappings,您可以假设这些字段以合理的方式映射到数据库,因为我觉得这不是问题所在。
当我尝试在测试中使用此查询时,如下所示:
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映射。我在QueryOver Series - Part 9: Extending QueryOver to Use Custom Methods and Properties看了安德鲁的例子,但感觉很像仪式
我也用谷歌搜索解决方案,但我的谷歌foo让我失望..
连连呢?溶液
答案 0 :(得分:1)
博客上的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
)
);
}