2011-02-16 22 views
0

我有一個遺留應用程序,數據庫中有一個可爲空的DateTime列 - NULL值用於表示+ Infinity。我的應用程序使用相當標準的NHibernate + DDD設置,包括Fluent-NHibernate和Linq2NHib。映射和查詢UserTypes - 數據庫中的可爲空數據庫爲不可空區域

我們假設我有以下代表實體的C#類。

class Discount 
{ 
    DateTime? ExpirationDate { get; set; } 
    // ... etc. 
} 

原來有管理這個ExpirationDate,我想封裝,例如,它必須是在午夜,並且可以有Infinity值的規則。在傳統應用NULL == Infinity中就像在數據庫中一樣。我想將它轉化成一些更喜歡這組類:

class Discount 
{ 
    OpenBusinessDate ExpirationDate { get; set; } // assume not nullable 
} 

class OpenBusinessDate // immutable 
{ 
    private DateTime _Value; 
    private bool _IsInfinity; 

    OpenBusinessDate(DateTime? value) 
    { 
     if (null == value) 
     { 
      _IsInfinity = true; 
      _Value = DateTime.MaxValue; // or SqlDateTime.MaxValue if you must 
     } 
     else 
     { 
      ErrorIfNotMidnight(value); 
      _Value = value; 
     } 
    } 

    DateTime ToDateTime() { return _Value; } 

    // ... casters, comparison methods, etc... 
} 

我目前沒有對所有現有的空值轉換成數據庫,以恆定的選項,但我喜歡我的域內查詢這樣的事情...

IList<Discount> GetAll(OpenBusinessDate expiringAfterDate) 
{ 
    return (from d in session.Linq<Discount>() 
      where d.ExperationDate > expiringAfterDate 
      select d).ToList(); 
} 

...並已NH知道翻譯成這個......

SELECT * FROM Discount 
WHERE (ExpirationDate IS NULL 
    OR ExpirationDate > @expiringAfterDate) 

/* ...or possibly this... */ 

SELECT * From Discount 
WHERE (COALESCE(ExpirationDate, '9999-12-31') > @expiringAfterDate) 

我一直在服用的NH看看用戶類型,並已取得了IUserType來轉換fr om InfinityNULL並返回(與實際的DateTime一起),但我還沒有發現如何讓查詢被寫入像我想要的。也就是說,現在,上面的LINQ和我的代碼會生成查詢:

SELECT * FROM Discount 
WHERE (ExpirationDate > 'Infinity') 
/* b/c OpenBusinessDate.ToString() on Infinity 
    produces "Infinity" for debugging purposes */ 

沒有人有哪裏看或具有類似工作的例子有什麼建議?我似乎無法找到正確的一組關鍵字來找到匹配的東西,我認爲這是一個解決的問題。這純粹是一個NH問題要解決,還是這也會涉及Linq2NH的一些工作?

回答

1

我會做的事情是這樣的映射保護財產的到期日期,然後公開公共的只讀屬性爲OpenBusinessDate像這樣:

public class Discount 
{ 
    private DateTime _value; 
    protected DateTime? ExpirationDate 
    { 
     get { return _value; } 
     set { 
       _value = value; 
       ExpirationDate = new OpenBusinessDate(value); 
      } 
    } 
    public OpenBusinessDate OpenExpirationDate {get; private set;} 
} 

,然後覆蓋的折扣類別的映射,如下所示:

public PersonMap : ClassMap<Discount> 
{ 
    public PersonMap() 
    { 
     Map(Reveal.Property<Discount>("ExpirationDate ")) 
    } 
} 

然後在LINQ查詢,你就可以自己申請無窮邏輯,像這樣

return (from d in session.Linq<Discount> 
      where d.ExpirationDate > expiringAfterDate || d.ExpirationDate != null 
      select d).ToList(); 
+0

這種類型的日期適用於我的域中的大量實體,我真的不想在每個查詢中重複「或null」檢查。它已經在過去造成了錯誤,並且使我必須重複更多的測試用例。但是,我沒有想過只使用DateTime的後臺?如果我做不好,這可能是一個很好的妥協。 – xero 2011-02-16 02:41:33

相關問題