2015-04-15 4 views
1

У меня есть таблица со 100 000 + записями. Клиент попросил, чтобы мы зашифровали поле имени пользователя, скопировали зашифрованное значение в новое поле и очистили исходное имя пользователя. Шифрование может выполняться только в приложении, а не в базе данных.Альтернатива массовому обновлению с помощью платформы Entity Framework

Существующая кодовая база ранее использовала Entity Framework для этих задач, но никогда не для таблицы такого размера. Наследство коды выглядели что-то вроде:

foreach(var phone in db.Phones){ 
    phone.Enc_Serial = Encrypt(phone.Serial); 
    phone.Serial = ""; 
} 
db.SaveChanges(); 

Учитывая это массовое обновление, будет ли какое-то преимущество, чтобы сделать это с помощью команды SQL сырой? Я думаю, что, по крайней мере, у нас не было бы тонны отслеживаемых объектов, сидящих в потребляющей памяти DbContext.

var idsAndSerials = db.Phones.Select(p => new { id = p.Id, serial = p.Serial }; 
foreach(var item in idsAndSerials){ 
    string sql = String.Format("Update phone set Enc_Serial ='{0}' where phoneId={1}", Encrypt(item.serial), item.id.ToString()); 
    db.Database.ExecuteSqlCommand(sql); 
} 
+1

Из любопытства, почему это имеет значение? Ваш унаследованный метод не может работать в достаточном количестве времени? Профилировали ли вы разницу между двумя методами для записей 1k? –

+3

Цикл foreach для одного обновления одновременно занимает много времени. Я бы посоветовал построить таблицу на конце C#, а затем вставить ее в таблицу Temp в базе данных и затем запустить одно обновление. – Hozikimaru

+1

Если вы сделаете это с помощью «* Raw SQL command *», то технически вы будете выполнять шифрование в базе данных и * не * в приложении. (Так как команды SQL запрошены * клиентом, но фактически * выполнены * сервером СУБД). – RBarryYoung

ответ

1

В примере, который вы предоставили, никоим образом. Вы все еще повторяете каждую запись и вызываете UPDATE. По крайней мере, в первом примере, я считаю, что эти утверждения будут исполняться как пакетные и будут транзакционными, чтобы все обновления были успешными или ни одна из них не выполнялась.

1

Поскольку это существенное обновление, я бы предложил создать таблицу отслеживания (на стороне SQL), в которой вы последовательно указываете каждую обновляемую строку (а также сохраняете значение PK строки). Также укажите столбец в таблице отслеживания, который позволяет вам пометить строку как выполненную (скажем 0 или 1). Установите внешний ключ в исходную таблицу с помощью значения PK.

Обновите свою модель данных на стороне EF, чтобы включить новую таблицу отслеживания. Теперь у вас есть новая таблица, которая легко позволит вам восстановить, скажем, 1 тыс. Записей, чтобы работать одновременно. Это не будет иметь чрезмерного потребления памяти. Логика приложения может выполнять шифрование. По мере обновления этих записей отметьте те, которые были обновлены как «сделанные» в вашей таблице отслеживания.

Получите следующие 1K незавершенных записей через таблицу отслеживания (используйте свойства навигации, чтобы получить реальные записи). Повторение.

Это будет сделано очень быстро и без излишней нагрузки. 100000+ записей на самом деле не очень много, особенно если вы используете подход «разделять» и «побеждать» (более 100 партий).

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