Проблемы с отображениями NHibernate и DateTime - PullRequest
4 голосов
/ 07 октября 2011

У меня возникли проблемы с запросом, в котором я выбираю записи за заданный промежуток времени.

Выбранный столбец имеет тип DATE.Я сопоставил этот столбец как свойство DateTime, и запрос работает, но работает медленно.

Сгенерированный запрос выглядит следующим образом: (предоставляется NHProfiler )

select kifkalende0_.KALENDER_MEDARBEJDER_ID as KALENDER1_119_0_,
   kifkalende1_.KALENDER_EMNE_ID        as KALENDER1_210_1_,
   kifkalende0_.OPDATERET_TIDSPUNKT     as OPDATERET2_119_0_,
   kifkalende0_.AENDRET                 as AENDRET119_0_,
   kifkalende0_.OPDATERET_AF            as OPDATERET4_119_0_,
   kifkalende0_.OPRETTET_AF             as OPRETTET5_119_0_,
   kifkalende0_.OPRETTET_TIDSPUNKT      as OPRETTET6_119_0_,
   kifkalende0_.SLETTET                 as SLETTET119_0_,
   kifkalende0_.KALENDER_EMNE_ID        as KALENDER8_119_0_,
   kifkalende0_.MEDARBEJDER_ID          as MEDARBEJ9_119_0_,
   kifkalende1_.OPDATERET_TIDSPUNKT     as OPDATERET2_210_1_,
   kifkalende1_.BESKRIVELSE             as BESKRIVE3_210_1_,
   kifkalende1_.DATO                    as DATO210_1_,
   kifkalende1_.ER_FRA_SAG              as ER5_210_1_,
   kifkalende1_.FRA_SAG_ID              as FRA6_210_1_,
   kifkalende1_.FRA_TABEL               as FRA7_210_1_,
   kifkalende1_.FRA_TID                 as FRA8_210_1_,
   kifkalende1_.OPDATERET_AF            as OPDATERET9_210_1_,
   kifkalende1_.OPRETTET_AF             as OPRETTET10_210_1_,
   kifkalende1_.OPRETTET_TIDSPUNKT      as OPRETTET11_210_1_,
   kifkalende1_.SAG_TYPE                as SAG12_210_1_,
   kifkalende1_.TIL_TID                 as TIL13_210_1_,
   kifkalende1_.YDERLIGERE_BESKRIVELSE  as YDERLIGERE14_210_1_,
   kifkalende1_.EMNE_ID                 as EMNE15_210_1_,
   kifkalende1_.PERSON_ID               as PERSON16_210_1_
from   "KIF_KALENDER_MEDARBEJDER" kifkalende0_
   left outer join "KIF_KALENDER_EMNE" kifkalende1_ on 
kifkalende0_.KALENDER_EMNE_ID = kifkalende1_.KALENDER_EMNE_ID,
   "KIF_KALENDER_EMNE" kifkalende2_
where  kifkalende0_.KALENDER_EMNE_ID = kifkalende2_.KALENDER_EMNE_ID
   and (kifkalende0_.MEDARBEJDER_ID in (7624 /* :p3 */,6226 
/* :p4 */,7382 /* :p5 */,5774 /* :p6 */, 5775 /* :p7 */,8259 
/* :p8 */,8218 /* :p9 */,9899 /* :p10 */, 6000 /* :p11 */,5779 
/* :p12 */,5780 /* :p13 */,5782 /* :p14 */, 5783 /* :p15 */,5784 
/* :p16 */,5785 /* :p17 */,5788 /* :p18 */, 5789 /* :p19 */,5790 
/* :p20 */,7341 /* :p21 */,8963 /* :p22 */, 10201 /* :p23 */,10388 
/* :p24 */))       
and kifkalende2_.DATO >= TIMESTAMP '2010-11-10 00:00:00.00' /* :p0 */
and kifkalende2_.DATO <= TIMESTAMP '2010-11-10 23:59:59.00' /* :p1 */
and (kifkalende0_.SLETTET = TIMESTAMP '1899-12-31 00:00:00.00' /* :p2 */
    or kifkalende0_.SLETTET is null);

И в нашей базе данных это занимает около 1500 мсек.

Если мы изменим запрос вручную на:

select kifkalende0_.KALENDER_MEDARBEJDER_ID as KALENDER1_119_0_,
   kifkalende1_.KALENDER_EMNE_ID        as KALENDER1_210_1_,
   kifkalende0_.OPDATERET_TIDSPUNKT     as OPDATERET2_119_0_,
   kifkalende0_.AENDRET                 as AENDRET119_0_,
   kifkalende0_.OPDATERET_AF            as OPDATERET4_119_0_,
   kifkalende0_.OPRETTET_AF             as OPRETTET5_119_0_,
   kifkalende0_.OPRETTET_TIDSPUNKT      as OPRETTET6_119_0_,
   kifkalende0_.SLETTET                 as SLETTET119_0_,
   kifkalende0_.KALENDER_EMNE_ID        as KALENDER8_119_0_,
   kifkalende0_.MEDARBEJDER_ID          as MEDARBEJ9_119_0_,
   kifkalende1_.OPDATERET_TIDSPUNKT     as OPDATERET2_210_1_,
   kifkalende1_.BESKRIVELSE             as BESKRIVE3_210_1_,
   kifkalende1_.DATO                    as DATO210_1_,
   kifkalende1_.ER_FRA_SAG              as ER5_210_1_,
   kifkalende1_.FRA_SAG_ID              as FRA6_210_1_,
   kifkalende1_.FRA_TABEL               as FRA7_210_1_,
   kifkalende1_.FRA_TID                 as FRA8_210_1_,
   kifkalende1_.OPDATERET_AF            as OPDATERET9_210_1_,
   kifkalende1_.OPRETTET_AF             as OPRETTET10_210_1_,
   kifkalende1_.OPRETTET_TIDSPUNKT      as OPRETTET11_210_1_,
   kifkalende1_.SAG_TYPE                as SAG12_210_1_,
   kifkalende1_.TIL_TID                 as TIL13_210_1_,
   kifkalende1_.YDERLIGERE_BESKRIVELSE  as YDERLIGERE14_210_1_,
   kifkalende1_.EMNE_ID                 as EMNE15_210_1_,
   kifkalende1_.PERSON_ID               as PERSON16_210_1_
from   "KIF_KALENDER_MEDARBEJDER" kifkalende0_
   left outer join "KIF_KALENDER_EMNE" kifkalende1_ on 
kifkalende0_.KALENDER_EMNE_ID = kifkalende1_.KALENDER_EMNE_ID,
   "KIF_KALENDER_EMNE" kifkalende2_
where  kifkalende0_.KALENDER_EMNE_ID = kifkalende2_.KALENDER_EMNE_ID
   and (kifkalende0_.MEDARBEJDER_ID in (7624 /* :p3 */,6226 
/* :p4 */,7382 /* :p5 */,5774 /* :p6 */, 5775 /* :p7 */,8259 
/* :p8 */,8218 /* :p9 */,9899 /* :p10 */, 6000 /* :p11 */,5779 
/* :p12 */,5780 /* :p13 */,5782 /* :p14 */, 5783 /* :p15 */,5784 
/* :p16 */,5785 /* :p17 */,5788 /* :p18 */, 5789 /* :p19 */,5790 
/* :p20 */,7341 /* :p21 */,8963 /* :p22 */, 10201 /* :p23 */,10388 
/* :p24 */))  
   and kifkalende2_.DATO>=to_date('10-11-2010 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
   and kifkalende2_.DATO<=to_date('10-11-2010 23:59:59', 'DD-MM-YYYY HH24:MI:SS')
   and (kifkalende0_.SLETTET=to_date('31-12-1899 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
   or kifkalende0_.SLETTET is null);

, он будет выполнен примерно за 50 мс.

Isесть ли способ заставить NHibernate генерировать to_date вместо метки времени для сравнения дат ??

Я немного запутался, как работает RegisterDateTimeTypeMappings в Oracle10gDialect, но я попытался расширить его, изменив метод на

            protected override void RegisterDateTimeTypeMappings()
            {
                    RegisterColumnType(DbType.Date, "DATE");
                    //RegisterColumnType(DbType.DateTime, "TIMESTAMP(4)");
                    RegisterColumnType(DbType.DateTime, "DATE");
                    RegisterColumnType(DbType.Time, "TIMESTAMP(4)");
            }

но это не помогло.

Наша среда:

  • .net (C #) 4.0
  • NHibernate 3.1.0, используется в основном черезLinq
  • ODP.Net 11.2.2.0 против Oracle 11g

У кого-нибудь есть какие-либо предложения?

Спасибо, ./Daniel

Ответы [ 2 ]

6 голосов
/ 08 ноября 2011

Я решил мою и вашу проблему, переопределив следующий класс NHibernate. NHProfiler будет по-прежнему отображать значение TIMESTAMP, но базовый параметр будет иметь тип DATE - который будет индексируемым, если в вашем столбце оракула также указан DateTime. Наведите указатель мыши на параметры в NHProfiler, чтобы увидеть, что я имею в виду - что-то вроде: : p0: TIMESTAMP - '2011-07-01 00: 00: 00.00' Дата вместо : p0: TIMESTAMP - '2011-07-01 00: 00: 00.00' Timestamp.

Я также использую Oracle 11g, C # .Net 4, Nhibernate 3.2.

public class OracleDataClientDriver2 : OracleDataClientDriver
{
    protected override void InitializeParameter(IDbDataParameter dbParam, string name, SqlType sqlType)
    {
        switch (sqlType.DbType)
        {
                //Timestamp columns not indexed by Oracle 11g date columns. - Use Date 
            case DbType.DateTime:
                base.InitializeParameter(dbParam, name, SqlTypeFactory.Date);
                break;
            default:
                base.InitializeParameter(dbParam, name, sqlType);
                break;
        }
    }
}
0 голосов
/ 07 октября 2011

Не должно быть никакого преобразования вообще, если параметры имеют правильный тип. TIMESTAMP или to_date () нужны только в том случае, если у вас есть метка времени в строковом типе. Если параметр введен правильно, он должен выглядеть следующим образом:

select
       tab.COL as col
   from
       TABLE tab
   where
       tab.COL = :p0;
:p0 = 01.01.2000 00:00:00 [Type: DateTime (0)]

Убедитесь, что вы передаете DateTime объекты в запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...