Вы обращаетесь к базе данных дважды за каждую итерацию цикла - один раз, чтобы получить строку, затем снова, чтобы обновить строку. Это не очень эффективно.
Вы должны работать партиями:
Получить набор строк заранее, выбрав диапазон, а не одно значение, то есть 0-100 для первой партии, 101-200 для следующей партии и т. Д. Это будет быстрее, если у вас есть кластеризованный индекс, определенный в столбце Код.
Создание контекста данных до входа в цикл
Внутри цикла, просто обновите объекты
Вызовите SubmitChanges () ПОСЛЕ того, как цикл завершится, это отправит все обновления в базу данных за одно соединение / транзакцию
Повторите для следующей партии
Вы должны настроить размер пакета, так как вы не можете быть уверены, какой размер пакета даст лучшую производительность - не вводите его жестко в приложение.
Кроме того, я бы использовал SingleOrDefault () с нулевой проверкой вместо Single (), если только вы не можете гарантировать, что всегда будет строка для любого значения i.
EDIT:
С точки зрения использования памяти контролировать намного сложнее, но это не свойственно LINQ to SQL, с этим должен справиться любой алгоритм пакетной обработки. Хотя я не рекомендую использовать GC.Collect () на практике, этого обычно достаточно в качестве обходного пути после обработки большой партии.
Вы также можете посмотреть на уменьшение количества данных, которые вы извлекаете за строку (в зависимости от того, сколько это нужно для начала). Вы можете создать новую сущность, которая сопоставляется с гораздо меньшим набором столбцов из одной и той же таблицы, возможно, только с одним или двумя, так что при выборе этой сущности вы получаете только те столбцы, с которыми намереваетесь начать работу. Это улучшит как скорость, так и объем занимаемой памяти, так как меньше данных передается по проводам, а объекты намного меньше.