2009-06-23 19 views
31

Tôi đang sử dụng NHibernate và gọi một thủ tục lưu trữ thông qua một truy vấn có tên:Làm thế nào C# giá trị có thể gõ giá trị được đặt trên NHibernate có tên là tham số IQuery?

<sql-query name="SearchStuff" read-only="true" cacheable="true"> 
    <return class="ResultEntity" /> 
    EXEC [SearchStuff] ?, ?, ? </sql-query> 

Nhiều người trong số các thông số thủ tục lưu trữ là cố tình nullable - điều này không thể thay đổi.

C#:

IQuery listQuery = this.Session.GetNamedQuery("SearchStuff"); 
listQuery.SetInt32(0, param1); 
listQuery.SetDateTime(1, param2); 
listQuery.SetString(2, param3); 
IList<ResultEntity> results = listQuery.List<ResultEntity>(); 

Thật không may, NHibernate không cung cấp bất kỳ SetXyz() phương pháp với nhiều loại giá trị nullable vì vậy tôi cố gắng thêm một số phương pháp mở rộng để bù đắp:

public static class QueryExtensions 
{ 
    public static void SetInt32(this IQuery query, int position, int? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetInt32(position, val.Value); 
     } 
     else 
     { 
      query.SetParameter(position, null); 
     } 
    } 

    public static void SetInt32(this IQuery query, string name, int? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetInt32(name, val.Value); 
     } 
     else 
     { 
      query.SetParameter(name, null); 
     } 
    } 

    public static void SetDateTime(this IQuery query, int position, DateTime? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetDateTime(position, val.Value); 
     } 
     else 
     { 
      query.SetParameter(position, null); 
     } 
    } 

    public static void SetDateTime(this IQuery query, string name, DateTime? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetDateTime(name, val.Value); 
     } 
     else 
     { 
      query.SetParameter(name, null); 
     } 
    } 
} 

Tôi đã thử các phiên bản khác nhau nhưng không hoạt động. Mã ở trên không thành công với lỗi:

System.ArgumentNullException : A type specific Set(position, val) should be called because the Type can not be guessed from a null value. 

Tôi cũng đã thử đơn giản là không đặt tham số nhưng NHibernate yêu cầu mọi thông số được đặt. Tôi đã thử sử dụng cả hai phiên bản vị trí và được đặt tên với cùng một kết quả.

Có cách nào để gán giá trị null để đánh giá các thông số đã nhập trong các truy vấn được đặt tên NHibernate không?

Trả lời

50

OK, hóa ra có một số ghi đè trên SetParameter cho phép loại được đặt rõ ràng. Ví dụ:

query.SetParameter(position, null, NHibernateUtil.Int32); 

Các phương pháp mở rộng đầy đủ (ví Int32 và DateTime chỉ) bây giờ là:

public static class QueryExtensions 
{ 
    public static void SetInt32(this IQuery query, int position, int? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetInt32(position, val.Value); 
     } 
     else 
     { 
      query.SetParameter(position, null, NHibernateUtil.Int32); 
     } 
    } 

    public static void SetInt32(this IQuery query, string name, int? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetInt32(name, val.Value); 
     } 
     else 
     { 
      query.SetParameter(name, null, NHibernateUtil.Int32); 
     } 
    } 

    public static void SetDateTime(this IQuery query, int position, DateTime? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetDateTime(position, val.Value); 
     } 
     else 
     { 
      query.SetParameter(position, null, NHibernateUtil.DateTime); 
     } 
    } 

    public static void SetDateTime(this IQuery query, string name, DateTime? val) 
    { 
     if (val.HasValue) 
     { 
      query.SetDateTime(name, val.Value); 
     } 
     else 
     { 
      query.SetParameter(name, null, NHibernateUtil.DateTime); 
     } 
    } 
} 
+0

Cảm ơn vì điều đó, giúp tôi :) – RhysC

+3

Nếu bạn trả lại đối tượng truy vấn từ những phương pháp bạn cũng nhận được đúng, ví dụ như chaining: public static IQuery SetDateTime (... ... truy vấn retrun; –

+0

phần mở rộng rắn ! –

3

Các phương pháp mở rộng đầy đủ (ví Int32 và chỉ DateTime) với chaining được bây giờ:

public static class QueryExtensions 
{ 
    public static IQuery SetInt32(this IQuery __query, int __position, int? __val) 
    { 
     var _query = __val.HasValue ? __query.SetInt32(__position, __val.Value) : __query.SetParameter(__position, null, NHibernateUtil.Int32); 

     return _query; 
    } 

    public static IQuery SetInt32(this IQuery __query, string __name, int? __val) 
    { 
     var _query = __val.HasValue ? __query.SetInt32(__name, __val.Value) : __query.SetParameter(__name, null, NHibernateUtil.Int32); 

     return _query; 
    } 

    public static IQuery SetDateTime(this IQuery __query, int __position, DateTime? __val) 
    { 
     var _query = __val.HasValue ? __query.SetDateTime(__position, __val.Value) : __query.SetParameter(__position, null, NHibernateUtil.DateTime); 

     return _query; 
    } 

    public static IQuery SetDateTime(this IQuery __query, string __name, DateTime? __val) 
    { 
     var _query = __val.HasValue ? __query.SetDateTime(__name, __val.Value) : __query.SetParameter(__name, null, NHibernateUtil.DateTime); 

     return _query; 
    } 
} 
+0

Cảm ơn, rbrock, cho phần bổ sung này vào các phần mở rộng ở trên. Đây chính xác là những gì tôi cần. :) –

10

Một cách khác để hoàn thành nó là:

query.SetParameter<int?>(0, null); 
query.SetParameter<DateTime?>(1, null); 
... 

Và cứ thế ...

Lưu ý biểu tượng ? làm cho kiểu gốc không thể vô hiệu.

Các vấn đề liên quan