2010-04-15 41 views
1

我有一個關於如何將傳統CHAR數據庫日期和時間字段合併爲一個.NET DateTime屬性在我的POCO here(謝謝Berryl!)如何結合回答StackOverflow問題。現在我正試圖獲得一個自定義的ICritera查詢來對付那個非常有用的DateTime屬性。這裏是我的查詢:如何比較在ICompositeUserType的NHibernate ICriteria查詢中使用.NET類型?

ICriteria criteria = 
    Session.CreateCriteria<InputFileLog>() 
    .Add(Expression.Gt(MembersOf<InputFileLog>.GetName(x => x.FileCreationDateTime), DateTime.Now.AddDays(-14))) 
    .AddOrder(Order.Desc(Projections.Id())) 
    .CreateCriteria(typeof(InputFile).Name) 
     .Add(Expression.Eq(MembersOf<InputFile>.GetName(x => x.Id), inputFileName)); 

IList<InputFileLog> list = criteria.List<InputFileLog>(); 

,這裏是它生成查詢:

SELECT this_.input_file_token as input1_9_2_, 
    this_.file_creation_date as file2_9_2_, 
    this_.file_creation_time as file3_9_2_, 
    this_.approval_ind as approval4_9_2_, 
    this_.file_id as file5_9_2_, 
    this_.process_name as process6_9_2_, 
    this_.process_status as process7_9_2_, 
    this_.input_file_name as input8_9_2_, 
    gonogo3_.input_file_token as input1_6_0_, 
    gonogo3_.go_nogo_ind as go2_6_0_, 
    inputfile1_.input_file_name as input1_3_1_, 
    inputfile1_.src_code as src2_3_1_, 
    inputfile1_.process_cat_code as process3_3_1_ 
FROM input_file_log this_ 
    left outer join go_nogo gonogo3_ on this_.input_file_token=gonogo3_.input_file_token 
    inner join input_file inputfile1_ on this_.input_file_name=inputfile1_.input_file_name 
WHERE this_.file_creation_date > :p0 and 
    this_.file_creation_time > :p1 and 
    inputfile1_.input_file_name = :p2 
ORDER BY this_.input_file_token desc; 
:p0 = '20100401', 
:p1 = '15:15:27', 
:p2 = 'LMCONV_JR' 

查詢正是我所期望的,其實,除了它實際上並沒有給我我想要的東西(所有在過去的2周內),因爲在數據庫中,它使用CHAR而不是DATE s進行比較。我不知道如何獲得查詢,以在查詢中將CHAR值轉換爲DATE,而無需執行CreateSQLQuery(),,我想避免。有人知道怎麼做嗎?

更新: 我一直在尋找嘗試使用Projections.SqlFunction()或公式來實現這一點,但目前爲止無濟於事。以下是我已經使用SqlFunction()的代碼,但我得到一個錯誤NHibernate.QueryException : property does not map to a single column: FileCreationDateTime

DateTime twoWeeksAgo = DateTime.Now.AddDays(-14); 
ICriteria criteria = 
    Session.CreateCriteria<InputFileLog>() 
    .Add(Restrictions.Gt(Projections.SqlFunction("to_date", NHibernateUtil.DateTime, Projections.Property(MembersOf<InputFileLog>.GetName(x => x.FileCreationDateTime))), twoWeeksAgo)) 
    //.Add(Expression.Gt(MembersOf<InputFileLog>.GetName(x => x.FileCreationDateTime), DateTime.Now.AddDays(-14))) 
    .AddOrder(Order.Desc(Projections.Id())) 
    .CreateCriteria(typeof(InputFile).Name) 
     .Add(Expression.Eq(MembersOf<InputFile>.GetName(x => x.Id), inputFileName)); 

我相信我在這裏做得不對因爲FileCreationDateTime使用自定義ICompositeUserType其拆分它不喜歡它仍然反正將.NET DateTime屬性分成兩個Oracle SQL CHAR列(有關詳細信息,請參閱此StackOverflow question)。

+0

很愚蠢,我不能接受我自己的答案,因爲我實際上已經在2周後發現它,甚至沒有其他人甚至試圖回答(或在他們的意見中缺乏任何明確的評論)。我想我會刪除這篇文章,即使我認爲這是一個有用的帖子,爲一個不起眼的NHibernate場景。 (我很明顯試圖得到一個反應/這個評論8o)。 – gabe 2010-05-13 16:24:33

回答

2

我終於明白了這一點!下面的代碼(出於某種原因StackOverflow的是使一些在這第一個代碼的方法的名稱片斷類型的語法顏色):

IList<InputFileLog> list = null; 
    DateTime twoWeeksAgo = DateTime.Now.AddDays(-14); 

    IProjection datePropProj = 
     DefaultStringFileCreationDateTimeType.GetFileCreationDateToDateSQLProjection(); 
    IProjection timePropProj = 
     DefaultStringFileCreationDateTimeType.GetFileCreationTimeToDateSQLProjection(); 

    IProjection dateConstProj = 
     DefaultStringFileCreationDateTimeType.GetFileCreationDateToDateSQLFunction(twoWeeksAgo); 
    IProjection timeConstProj = 
     DefaultStringFileCreationDateTimeType.GetFileCreationTimeToDateSQLFunction(twoWeeksAgo); 

    ICriteria criteria = 
     Session.CreateCriteria<InputFileLog>() 
     .Add(Restrictions.Or(Restrictions.GtProperty(datePropProj, dateConstProj), 
      Restrictions.And(Restrictions.EqProperty(datePropProj, dateConstProj), 
       Restrictions.GeProperty(timePropProj, timeConstProj)))) 
     .AddOrder(Order.Desc(Projections.Id())) 
     .CreateCriteria(typeof(InputFile).Name) 
      .Add(Expression.Eq(MembersOf<InputFile>.GetName(x => x.Id), inputFileName)); 

    list = criteria.List<InputFileLog>(); 

,這裏是我用來創建SQLProjectionsSQLFunctions方法。我把它們放在我用於FileCreationDateTime屬性上的自定義類型映射的ICompositeUserTypeDefaultStringFileCreationDateTime)中。

public class DefaultStringFileCreationDateTime : ICompositeUserType 
{ 
    . 
    . 
    . 
    public const string DotNetDateFormat = "yyyyMMdd"; 

    public const string DotNetTimeFormat = "HH:mm:ss"; 

    public const string DbDateFormat = "YYYYMMDD"; 

    public const string DbTimeFormat = "HH24:MI:SS"; 

    private const string _nullDateRepresentationInDb = "00000000"; 

    public struct DatabaseFieldNames 
    { 
     /// <summary> 
     /// File creation date column name. 
     /// </summary> 
     public const string FileCreationDate = "file_creation_date"; 

     /// <summary> 
     /// File creation time column name. 
     /// </summary> 
     public const string FileCreationTime = "file_creation_time"; 
    } 

    public static IProjection GetFileCreationDateToDateSQLProjection() 
    { 
     return ProjectionUtil.GetToDateSQLProjection(DatabaseFieldNames.FileCreationDate, DbDateFormat, NHibernateUtil.DateTime); 
    } 

    public static IProjection GetFileCreationTimeToDateSQLProjection() 
    { 
     return ProjectionUtil.GetToDateSQLProjection(DatabaseFieldNames.FileCreationTime, DbTimeFormat, NHibernateUtil.DateTime); 
    } 

    public static IProjection GetFileCreationDateToDateSQLFunction(DateTime dt) 
    { 
     return ProjectionUtil.GetToDateSQLFunction(dt, DotNetDateFormat, DbDateFormat); 
    } 

    public static IProjection GetFileCreationTimeToDateSQLFunction(DateTime dt) 
    { 
     return ProjectionUtil.GetToDateSQLFunction(dt, DotNetTimeFormat, DbTimeFormat); 
    } 
} 

我已經使用constsDatabaseFieldNamesstructPropertyNames成員實現,所以我能夠重新用於Projections我需要以及這些硬編碼列名。

這裏的Projection實用工具類,其中通用to_date方式生活:

public class ProjectionUtil 
{ 
    public static IProjection GetToDateSQLProjection(
     string columnName, string dbToDateFormat, IType returnType) 
    { 
     return Projections.SqlProjection(
      string.Format("to_date({0}, '{1}') as {0}", columnName, dbToDateFormat), 
      new string[] { columnName }, 
      new IType[] { returnType }); 
    } 

    public static IProjection GetToDateSQLFunction(
     DateTime dt, string dotNetFormatString, string dbFormatString) 
    { 
     return Projections.SqlFunction(
      "to_date", 
      NHibernateUtil.DateTime, 
      Projections.Constant(dt.ToString(dotNetFormatString)), 
      Projections.Constant(dbFormatString)); 
    } 
} 

最後,下面是NHibernate的生成的Oracle SQL:

SELECT 
    this_.input_file_token as input1_9_2_, 
    this_.file_creation_date as file2_9_2_, 
    this_.file_creation_time as file3_9_2_, 
    this_.approval_ind as approval4_9_2_, 
    this_.file_id as file5_9_2_, 
    this_.process_name as process6_9_2_, 
    this_.process_status as process7_9_2_, 
    this_.input_file_name as input8_9_2_, 
    gonogo3_.input_file_token as input1_6_0_, 
    gonogo3_.go_nogo_ind as go2_6_0_, 
    inputfile1_.input_file_name as input1_3_1_, 
    inputfile1_.src_code as src2_3_1_, 
    inputfile1_.process_cat_code as process3_3_1_ 
FROM 
    input_file_log this_ 
    left outer join go_nogo gonogo3_ on this_.input_file_token=gonogo3_.input_file_token 
    inner join input_file inputfile1_ on this_.input_file_name=inputfile1_.input_file_name 
WHERE 
    (
     to_date(file_creation_date, 'YYYYMMDD') > to_date(:p0, :p1) or 
     (
      to_date(file_creation_date, 'YYYYMMDD') = to_date(:p2, :p3) and 
      to_date(file_creation_time, 'HH24:MI:SS') >= to_date(:p4, :p5) 
     ) 
    ) and 
    inputfile1_.input_file_name = :p6 
ORDER BY this_.input_file_token desc; 
:p0 = '20100415', 
:p1 = 'YYYYMMDD', 
:p2 = '20100415', 
:p3 = 'YYYYMMDD', 
:p4 = '18:48:48', 
:p5 = 'HH24:MI:SS', 
:p6 = 'LMCONV_JR' 

不能相信我有這個!我以爲我不得不求助於ISQLQuery

相關問題