2013-09-04 3 views
0

Я знаю, что это популярная проблема, и другие решения были предложены другим, но моя немного отличается.NHibernate внезапно очень медленно - необъяснимое поведение

Во-первых, это началось внезапно с двух дней назад, и ничто не изменилось на уровне NHibernate, чтобы объяснить такое изменение в поведении.

Я использовал dotTrace и развернулся к нему и обнаружил, что для выполнения некоторых кешированных запросов требуется до 70 секунд (т. Е. Метод GetAllCountries(), который возвращает список объектов страны).

70 секунд довольно сумасшедший для такого простого запроса, который не имеет внешних ссылок.

dotTrace показывает, что он называется CachedCountryService, который должен немедленно вернуть список. Вместо этого он в конечном итоге приводит к CountryService, который выполняет 70 секунд чтения.

База данных - mySQL.

Присоединенное изображение отчета dotTrace

An attached image of the dotTrace report

Объект Страна выглядит следующим образом:

public class CountryMapping : ClassMap<Country> 
    { 
     public CountryMapping() 
     { 
      Table("ma_tbl_country"); 

      Id(t => t.Id, "id"); 
      Map(t => t.Code, "code"); 
      Map(t => t.Name, "name"); 
      Map(t => t.Match, "`match`"); 

      References(t => t.RiskGroup).Column("RiskId"); 

      HasManyToMany(t => t.PaymentOptions) 
       .Table("ma_tbl_country_payment_option") 
       .ParentKeyColumn("country_id") 
       .ChildKeyColumn("payment_option_id").Cascade.SaveUpdate(); 
     } 
    } 

инициализаторе не влияет на объект страны, хотя Управление и счета используются в anoher NHibernate, который работает очень плохо (занимает 30 секунд).

public NHibernateInitializer() 
     { 
      base. 
      ExtraConfiguration = 
       t => 
        t.Mappings(s => s.FluentMappings.AddFromAssemblyOf<DAL.Mappings.OfficeMapping>().Conventions.Add(typeof(DisableLazyLoadConvention))) 
        .Mappings(s => s.FluentMappings.AddFromAssemblyOf<AccountMapping>().Conventions.Add(AutoImport.Never())); 
     } 

И DefaultLazyConvention является частью внутренней библиотеки, которая делает это:

public class DisableLazyLoadConvention : IHibernateMappingConvention, IConvention<IHibernateMappingInspector, IHibernateMappingInstance>, IConvention 
    { 
    public void Apply(IHibernateMappingInstance instance) 
    { 
     instance.Not.DefaultLazy(); 
    } 
    } 

UPDATE:

Я добавил уровень SQL профилирование и результаты buffling.

У меня есть два разных проекта, выполняющих один и тот же код, и я получаю запросы на 324 sql в медленных проектах, выполняющих 100 секунд для запуска, а затем 324 ИДЕНТИЧЕСКИХ запросов в другом проекте, занимающих 1 секунду!

Таким образом, я считаю, что проблема заключается в конфигурации NHibernate, а не в коде, потому что эти два набора запросов идентичны с использованием одних и тех же моделей домена. Они также используют одну и ту же базу данных с одним и тем же пользователем.

+0

У вас установлен уровень регистрации NHibernate на «DEBUG»? Попробуйте изменить его на «WARN» или «ERROR». –

+0

Я вижу изображение просто отлично. –

+0

У меня есть это ВСЕ, потому что я пытаюсь просмотреть запросы. До того, как он был на ERROR, и он ничего не записывал. Запросы не терпят неудачу, они просто берут навсегда. И это только конкретные запросы – Nick

ответ

0

FINALLY получил это решение.

Это не был NHibernate! Вот почему это было невозможно решить.

Проблема была вызвана этим пакетом под названием Combres. Он устанавливается через Nuget с большим количеством зависимостей. В одном из моих проектов одна из зависимостей была немного более высокой, чем ожидалось.

Когда я удалил его и снова установил, он установил правильные версии DLL на место (несколько более старые), и это заставило проект работать молниеносно!

Если кто-либо попадает в такую ​​трудную проблему, я надеюсь, что это поможет им разрешить это.

0

Из вашего снимка dotTrace, пожалуйста, обратите внимание, что InitializeNonLazyCollections занимает почти все время.

DisableLazyLoadConvention применяется не только к Office. Он применяется ко всем ClassMap с в той же сборке, что и OfficeMapping. Условные обозначения используются для применения сопоставлений с широкими штрихами кисти по всему вашему приложению. Например, вы можете использовать их, чтобы говорить такие вещи, как «Всякий раз, когда вы видите свойство DateTime, чье имя заканчивается« Utc », нарисуйте его, используя .CustomType("UtcDateTime")».

Если вам необходимо применить специальные сопоставления только к одному классу, сделайте это в ClassMap (для плавного отображения) или в IAutoMappingOverride (для автоматического сопоставления). Если вы хотите изменить отображение для каждого класса, это когда вы используете соглашения.

Удалите .Conventions.Add(typeof(DisableLazyLoadConvention)) со своего кода инициализации NHibernate и замените его более целенаправленными вызовами на .Not.LazyLoad() в OfficeMapping.

+0

Очень перспективный. Позвольте мне проверить – Nick

+0

Если я удалю это соглашение, я получаю: «Метод get_Id должен быть« общедоступным/защищенным виртуальным »или« защищенным внутренним виртуальным »на всех классах сущностей в системе. – Nick

+0

В этой строке есть проблема: CurrentSessionContext.Bind (nHibernateContext.SessionFactory.OpenSession()); – Nick

Смежные вопросы