Как вы сравните с помощью типов .NET в запросе Nhibernate Icriteria для icompositeusertype?
-
27-09-2019 - |
Вопрос
У меня есть вопрос о том, как сочетать на наследие CHAR
Дата и временные поля базы данных в один .NET DateTime
Недвижимость в моем POCOздесь (Спасибо большое Ягода!). Теперь я пытаюсь получить пользовательский запрос Icritera, чтобы работать против этого DateTime
недвижимость безрезультатно. Вот мой запрос:
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
с. Я понятия не имею, как получить запрос для преобразования 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 делает некоторые из названий методов в этом фрагменте первого кода Синтаксис цвета типа):
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>();
И вот методы, которые я использовал для создания SQLProjections
а также SQLFunctions
. Отказ Я положил их в мой ICompositeUserType
(DefaultStringFileCreationDateTime
) что я использовал для отображения пользовательского типа на FileCreationDateTime
имущество.
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);
}
}
Я уже использовал consts
DatabaseFieldNames
struct
для PropertyNames
Реализация членов, поэтому я смог повторно использовать эти жестко закодированные имена столбцов для Projections
Мне тоже нужно было.
Вот то Projection
Утилита, где общий to_date
Методы Live:
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));
}
}
Наконец, вот Oracle SQL, который генерирует Nibernate:
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
для уверенности!