sobota, 15 września 2012

Wstawianie wielu rekordów za pomocą LINQ - Batch Instert by LINQ

Wielu sobie zadaje pytanie dlaczego wstawianie dużej ilości rekordów do bazy za pomocą LINQ2SQL bądź też Entity Framework trwa tak długo.

Zobaczmy na poniższy kawałek kodu:


Code:
        static void Main(string[] args)
        {
            var test1Context = new test1Context();
            test1Context.Configuration.AutoDetectChangesEnabled = false;
            test1Context.Configuration.ProxyCreationEnabled = false;
            for (int i = 0; i < 1000; i++)
            {
                var pojazd = new Pojazd {Nazwa = Guid.NewGuid().ToString()};
                test1Context.Pojazds.Add(pojazd);
            }

            test1Context.SaveChanges();
        }

Wydawałoby się że zostanie wykonana pojedyncza transakcja, która wstawi wszystkie rekordy. Przyglądając się profilerowi MS SQL możemy stwierdzić, że tak się nie dzieje:

EXEC sp_executesql N'insert [dbo].[Pojazd]([Nazwa])
values (@0)
select [Id]
from [dbo].[Pojazd]
where @@ROWCOUNT > 0 and [Id] = scope_identity()'
,N'@0 nchar(100)',@0=N'6dd1fb44-61d3-4fce-8ef8-4f0d61492df2       
'


Każdy rekord jest traktowany osobno, a dodatkowo pobierane jest jego Id. Mamy więc do czynienia z sekwencją: wstaw rekord, pobierz Id, przypisz Id do obiektu.

W jaki sposób poradzić sobie z tym problemem? Na ten moment nie ma jednego uniwersalnego rozwiązania zawartego w EF czy też LINQ2SQL. Niestety musimy sami zaimplementować takie rozwiązanie, korzystając z klas do szybkiego wstawiania rekordów do tabel oferowanych przez poszczególnych providerów komponentów do obsługi baz danych. Innym rozwiązaniem jest napisanie własnego "czystego" SQLa który wykonuje INSERT do bazy przy użyciu transakcji. 

Brak komentarzy:

Prześlij komentarz