Entity Framework медленное первое соединение с БД - PullRequest
1 голос
/ 24 марта 2019

Первое подключение к базе данных в моем приложении (EF 6.2, сначала код) очень медленное, есть ли способ изменить OnModelCreating часть моего DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        var typesToRegister = Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(type => !String.IsNullOrEmpty(type.Namespace))
            .Where(type => type.BaseType != null
            && type.BaseType.IsGenericType
            && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));

        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(configurationInstance);
        }

        base.OnModelCreating(modelBuilder);
}

В режиме отладки Iвидите, что это причина того, что инициализация соединения занимает несколько десятков секунд ...

Ответы [ 2 ]

2 голосов
/ 24 марта 2019

Первый Entity Framework Query всегда медленный, потому что EF компилирует вашу модель и генерирует представления отображения в памяти.

Вы можете предварительно сгенерировать эти представления отображения, используяEF Power Tools.Вот документация для этого здесь, на docs.microsoft.com .

. Для загрузки этих представлений вам необходимо создать собственный класс DbConfiguration, подобный этому:

public class MyDbConfiguration : DbConfiguration
{
    public MyDbConfiguration() : base()
    {
        var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
        SetModelStore(new DefaultDbModelStore(path));
    }
}

использование:

[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext 
{
}

Дополнительная информация о DbConfiguration: здесь

Что еще можно сделать, если ваше приложение не работает в Azure SQL это использовать CustomManifestTokenResolver, как этот

public class CustomManifestTokenResolver : IManifestTokenResolver
{
    public string ResolveManifestToken(DbConnection connection)
    {
        return "2012";
    }

}

Чтобы использовать его, вы должны добавить его в свой класс DbConfiguration

public class MyDbConfiguration : DbConfiguration
{
    public MyDbConfiguration() : base()
    {
        var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
        SetModelStore(new DefaultDbModelStore(path));
        SetManifestTokenResolver(new CustomManifestTokenResolver());
    }
}

Другая проблема с производительностью во время запуска - просто-в-время составления сборок EF.Вы можете использовать ngen, чтобы обойти это (предполагается, что ваши сборки находятся в папке bin \ release.

%WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\release\EntityFramework.dll
 %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\release\EntityFramework.dll
 %WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\release\EntityFramework.SqlServer.dll
 %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\release\EntityFramework.SqlServer.dll
 %WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\debug\EntityFramework.dll
 %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\debug\EntityFramework.dll
 %WINDIR%\Microsoft.NET\Framework\v4.0.30319\ngen install .\bin\debug\EntityFramework.SqlServer.dll
 %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install .\bin\debug\EntityFramework.SqlServer.dll

Для общих проблем с производительностью EF у меня есть репозиторий на github где я демонстрирую общие проблемы и решения этих проблем.

Обновление: добавлен трюк при запуске

Что-то, что мы используем в нашем программном обеспечении, - это выполнение пустого запросаво время запуска. Предполагая, что у нас есть контекст с именем MyContext и DbSet с именем Customers, мы будем писать что-то подобное во время запуска:

using(var db = new MyContext())
{
   db.Customers.Where(x=> x.Id < 0).ToList();   // There are no negative Ids, so this will always be and empty list
}

Это переместит ваш код инициализации в фазу запускаваше приложение. Из-за этого пользователь не будет иметь медленный опыт для первого реального запроса в системе. Вы можете даже сделать это асинхронно. Вы просто должны убедиться, что нет других вызовов вашего контекста из других потоков вв то же время, потому что DbContext не является ThreadSafe.

0 голосов
/ 24 марта 2019

Вы можете удалить часть отражения и просто передать типы вручную. Отражение - это медленная задача, и вы не можете ожидать быстрого опыта с чем-то, что использует отражение, но, поскольку это только для первого соединения, мне лично было бы все равно, если не так важно начать очень быстро.

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