2015-10-16 65 views
1

我已經在一個帶有屬性的類中定義了一個查詢,但我試圖使用這個屬性來構建一個相當複雜的查詢,並且碰到NHibernate告訴我它無法解析屬性:DueDate 。QueryOver使用自定義投影和查詢參數

我的查詢類看起來是這樣的:

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

完全按照安德魯·惠特克的博客中描述QueryOver Series - Part 7: Using SQL Functions

PrimaryObjectSubObject的內容我已經實現了DateProjections類是不是真的很重要以下示例除外:

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映射。我看過安德魯在QueryOver Series - Part 9: Extending QueryOver to Use Custom Methods and Properties的例子,但感覺好像很多儀式。

我也用Google搜索的解決方案,但我的谷歌富失敗我..

建議?解決方案?

+0

是實際的DateDiff調用周圍的代碼?它看起來不像可編譯的C#代碼。 –

+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 
     ) 
); 
} 
+1

沒有什麼比貨物查詢,別人的代碼沒有真正理解它在做什麼。在使用QueryOver和Projections時,您的示例擴展了我的理解。 –