Подтвердить что ты не робот

Структура Entity очень медленно загружается в первый раз после каждой компиляции

Как видно из названия, у меня возникла проблема с первым запросом в базе данных SQL Server с использованием Entity Framework. Я попытался найти ответ, но никто, кажется, не имеет решения для этого.

Тесты были выполнены в Visual Studio 2012 с использованием Entity Framework 6, я также использовал шаблон представлений T4 для предварительной компиляции представлений. База данных была на SQL Server 2008. У нас есть около 400 POCOs (400 файлов сопоставления), в таблице базы данных есть только 100 строк.

Следующий захват - это мой тестовый код и результат.

static void Main(string[] args){
    Stopwatch st=new Stopwatch();
    st.Start();
    new TestDbContext().Set<Table1>.FirstOrDefault();
    st.stop();
    Console.WriteLine("First Time "+st.ElapsedMilliseconds+ " milliseconds");

    st.Reset();
    st.Start();
    new TestDbContext().Set<Table1>.FirstOrDefault();
    st.stop();
    Console.WriteLine("Second Time "+st.ElapsedMilliseconds+ " milliseconds");
}

Результаты тестов

First Time 15480 milliseconds
Second Time 10 milliseconds
4b9b3361

Ответ 1

В первом запросе EF компилирует модель. Это может занять некоторое серьезное время для такой большой модели.

Вот 3 предложения: http://www.fusonic.net/en/blog/2014/07/09/three-steps-for-fast-entityframework-6.1-first-query-performance/

Резюме:

  • Использование хранилища моделей кэшированных db
  • Создание предварительно скомпилированных представлений
  • Сгенерируйте предварительно скомпилированную версию сущностной схемы, используя n-gen, чтобы избежать джитта

Я также должен убедиться, что я компилирую приложение в режиме выпуска при выполнении тестов.

Другим решением является просмотр разделения DBC-контекста. 400 объектов много, и лучше работать с меньшими кусками. Я не пробовал, но я предполагаю, что можно будет строить модели один за другим, что означает, что ни одна загрузка не занимает 15 секунд. См. Это сообщение Julie Lerman https://msdn.microsoft.com/en-us/magazine/jj883952.aspx

Ответ 2

эта работа для меня:

using (MyEntities db = new MyEntities())                
{
   db.Configuration.AutoDetectChangesEnabled = false; // <----- trick
   db.Configuration.LazyLoadingEnabled = false; // <----- trick

   DateTime Created = DateTime.Now;

   var obj = from tbl in db.MyTable
      where DateTime.Compare(tbl.Created, Created) == 0
      select tbl;

   dataGrid1.ItemsSource = obj.ToList();
   dataGrid.Items.Refresh();
}

Ответ 3

эта работа для меня:

using (MyEntities db = new MyEntities())                
        {
           db.Configuration.AutoDetectChangesEnabled = false; // <----- trick
           db.Configuration.LazyLoadingEnabled = false; // <----- trick

           DateTime Created = DateTime.Now;

           var obj = from tbl in db.MyTable
              where DateTime.Compare(tbl.Created, Created)  0
              select tbl;

           dataGrid1.ItemsSource = obj.ToList();
           dataGrid.Items.Refresh();
        }

Ответ 4

Вы можете попробовать что-то вроде этого: (это сработало для меня)

protected void Application_Start()
{

    Start(() =>
    {
        using (EF.DMEntities context = new EF.DMEntities())
        {
            context.DMUsers.FirstOrDefault();
        }
    });
}
private void Start(Action a)
{
    a.BeginInvoke(null, null);
} 

Entity Framework - первый запрос медленный

Ответ 5

Если у вас много таблиц, которые не используются на С#, исключите их.

Добавьте частичный класс, добавьте следующий код и обратитесь к этой функции в OnModelCreating

void ExcludedTables(DbModelBuilder modelBuilder)
{
    modelBuilder.Ignore<Table1>();
    modelBuilder.Ignore<Table>();
   // And so on
}

Ответ 6

С EF Ядром, вы можете обмануть и загрузить модель рано после вызова services.AddDbContext (вы, вероятно, можете сделать что - то подобное с EF6 тоже, но я не проверял).

services.AddDbContext<MyDbContext>(options => ...);
var options = services.BuildServiceProvider()
                      .GetRequiredService<DbContextOptions<MyDbContext>>();
Task.Run(() =>
{
    using(var dbContext = new MyDbContext(options))
    {
        var model = dbContext.Model; //force the model creation
    }
});

Это создаст модель dbcontext в другом потоке, в то время как остальная часть инициализации приложения будет выполнена (и, возможно, другие разминки) и начало запроса. Таким образом, он будет готов раньше. Когда вам это нужно, EFCore будет ждать создания Модели, если она еще не закончена. Model разделяется во всех экземплярах DbContext, поэтому нормально запускать и забывать этот фиктивный dbcontext.