Производительность Devart Oracle Entity Framework 4.1 - PullRequest
0 голосов
/ 07 сентября 2011

Я хочу знать, почему фрагмент кода 1 быстрее, чем код 2, использующий POCO с Devart DotConnect для Oracle.

Я пробовал более 100000 записей, и Код 1 работает быстрее, чем 2. Почему?Я думал, что «SaveChanges» очистит буфер, делая его быстрее, поскольку есть только 1 соединение.Я не прав?

Код 1:

        for (var i = 0; i < 100000; i++)
        {
            using (var ctx = new MyDbContext())
            {
                MyObj obj = new MyObj();
                obj.Id = i;
                obj.Name = "Foo " + i;
                ctx.MyObjects.Add(obj);
                ctx.SaveChanges();
            }
        }

Код 2:

        using (var ctx = new MyDbContext())
        {
            for (var i = 0; i < 100000; i++)
            {
                MyObj obj = new MyObj();
                obj.Id = i;
                obj.Name = "Foo " + i;
                ctx.MyObjects.Add(obj);
                ctx.SaveChanges();
            }
        }

1 Ответ

3 голосов
/ 07 сентября 2011

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

Во втором случае 100 000 объектов постепенно добавляются в контекст. Используется медленное отслеживание на основе снимков (если динамический прокси отсутствует). Это приводит к обнаружению, если какие-либо изменения в любом из кэшированных объектов произошли в каждом SaveChanges (). На каждую последующую итерацию тратится все больше и больше времени.

Рекомендуем попробовать следующий подход. Он должен иметь лучшую производительность, чем упомянутые:

using (var ctx = new MyDbContext())
    {
        for (var i = 0; i < 100000; i++)
        {
            MyObj obj = new MyObj();
            obj.Id = i;
            obj.Name = "Foo " + i;
            ctx.MyObjects.Add(obj);                
        }
        ctx.SaveChanges();
    }

EDIT

Если вы используете подход с выполнением большого количества операций в одном SaveChanges (), будет полезно дополнительно настроить поведение Entity Framework Devart dotConnect для провайдера Oracle:

// Turn on the Batch Updates mode:
var config = OracleEntityProviderConfig.Instance;
config.DmlOptions.BatchUpdates.Enabled = true;

// If necessary, enable the mode of re-using parameters with the same values:
config.DmlOptions.ReuseParameters = true;

// If object has a lot of nullable properties, and significant part of them are not set (i.e., nulls), omitting explicit insert of NULL-values will decrease greatly the size of generated SQL:
config.DmlOptions.InsertNullBehaviour = InsertNullBehaviour.Omit;

Здесь упоминаются только некоторые варианты. Полный их список доступен в нашей статье: http://www.devart.com/blogs/dotconnect/index.php/new-features-of-entity-framework-support-in-dotconnect-providers.html

Неправильно ли предположить, что при вызове SaveChanges () все объекты в кеше хранятся в БД и кеш очищается, поэтому каждый цикл независим?

SaveChanges () отправляет и фиксирует все изменения в базе данных, но отслеживание изменений продолжается для всех объектов, которые присоединены к контексту. И новые SaveChanges, если используется отслеживание изменений на основе снимков, запустят длительный процесс проверки (изменены или нет?) Значений каждого свойства для каждого объекта.

...