2012-02-24 4 views
0

Я использую AutoMapper для отображения объектов из унаследованной базы данных в новую базу данных, объявленных в EF коде первый:Улучшение производительности инициализации DbSet в семенах?

StartTimer("Map Customers");  
     var mfpCustomers = Mapper.Map<IEnumerable<LegacyDataModel.Customer>, IEnumerable<Customer>>(
     legacyEntities.Customers.Include(p => p.Demographics).ToList()); 
     StopAndPrintTimer("Map Customers"); 

     StartTimer("Iterate Customers"); 
     foreach (var p in mfpCustomers) 
     { 
     db.Customers.Add(p);  
     } 
     StopAndPrintTimer("Iterate Customers"); 

для каждого является то, что занимает больше всего времени. Я хотел бы сопоставить непосредственно с DbSet(db.Customer), вместо того, чтобы делать foreach над db.Customers.Add(p);. Я не понял, как это сделать, хотя нет ничего похожего на метод AddRange, разработанный специально для добавления большого количества объектов. Я знаю, как делать эти типы преобразований с помощью основанных на наборе методов в SQL, но это безумная сумма ввода, потому что intellisense не работает так хорошо в этих сценариях в SSMS.

Этот код не обязательно должен быть очень быстрым, но для того, чтобы ждать полной минуты каждый раз, когда я семя, база данных делает сложную работу (и ее нужно часто перекладывать из-за быстрой разработки новой базы данных) , Обратите внимание также, что, поскольку это метод семени, я не против полностью заменить существующих клиентов (поскольку их нет). Поэтому в этом отношении не нужно вести себя как AddRange, так как я просто создаю новую коллекцию.

Любые идеи о том, как я могу улучшить производительность здесь? Любые идеи о том, как я могу отобразить всю коллекцию непосредственно в DbSet, не делая foreach на каждом экземпляре?

ответ

1

Каждый раз, когда вы вызываете db.Customers.Add (p), EF вызывает вызов DetectChanges, чтобы узнать, изменилось ли что-либо в графе сущности. Это помогает сделать работу так, как ожидалось, когда Add вызывается после внесения изменений в другие объекты. Тем не менее, DetectChanges может замедляться, если в контексте есть много объектов - у него есть O (n) время на количество сущностей. Поэтому в таких случаях, как у вас, это может иметь большое значение, если вы временно включаете эти автоматические вызовы в DetectChanges. Например:

try 
{ 
    context.Configuration.AutoDetectChangesEnabled = false; 

    foreach (var p in mfpCustomers) 
    { 
     db.Customers.Add(p);   
    } 
} 
finally 
{ 
    context.Configuration.AutoDetectChangesEnabled = true; 
} 

Вы можете найти более подробную информацию здесь: http://blogs.msdn.com/b/adonet/archive/2011/02/06/using-dbcontext-in-ef-feature-ctp5-part-12-automatically-detecting-changes.aspx

+0

Это здорово. Кажется, что быстрее, если я вызову SaveChanges, прежде чем я верну автообнаружение в true. Будет ли он правильно сохранять или по каким-либо причинам делать один за другим? После реализации этого я заметил что-то странное, где часто мой инициализатор вообще не вызывался, хотя я использовал DropCreateDatabaseAlways. Мне действительно нужно было очистить и перестроить проект, чтобы заставить его вызвать мою функцию семени. – AaronLS

+0

В этом случае следует сохранить штраф, если вы вызываете SaveChanges перед тем, как снова включить DetectChanges. Если вы делаете какие-либо другие манипуляции с сущностями между их добавлением и вызовом SaveChanges, это может быть неправильно сохранено. –

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