LINQ - Должен ли я как-то периодически отправлять SubmitChanges(), если у меня много изменений?

У меня есть группа "роботов", которые бегают вокруг чтения RSS-потоков и сохраняют результаты в базе данных, и я распараллелил их так, чтобы можно было получать сразу несколько каналов:

Parallel.ForEach(context.Feeds, feed => ProcessRssFeed(feed, context));
context.SubmitChanges();

Функция ProcessRssFeed может вставлять записи в контекст по мере их обнаружения, и каждый фид может содержать от нуля до сотен элементов. Существует много каналов, поэтому я не хотел создавать LINQ DataContext для каждого.

Тем не менее, я обеспокоен тем, что мог бы накапливать тысячи на тысячи записей на клиенте. Я полагаю, мне не хватит памяти.

Поскольку здесь нет проблем с параллелизмом, если бы это было возможно, я бы хотел сказать DataContext: "Продолжайте и периодически отправляйте записи, если хотите". Есть ли практический способ для достижения этой цели?

2 ответа

Решение

Я бы порекомендовал создать новый DataContext для каждого. DataContexts довольно легки по сравнению с фактическим подключением к базе данных. DataContext при подключении к базе данных использует пул соединений, при использовании отдельных DataContexts вы не получите больших накладных расходов.

Сохраняйте в DataContext только те вещи, которые необходимо атомарно передать, отправьте их и создайте новый DataContext для следующего элемента.

Не существует встроенного метода для периодической отправки, но вы можете посмотреть количество элементов в DataContext.GetChangeSet() и отправить, когда этот счет превышает заданный порог. Но делать это следует только в том случае, если профилирование показывает, что создание новых DataContexts действительно является узким местом в вашей системе.

Если у вас есть много объектов, которые содержат довольно мало данных, вы можете начать увеличивать использование памяти. DataContext хранит все отслеженные изменения в памяти до тех пор, пока вы не вызовете SubmitChanges. Я бы порекомендовал измерить использование памяти вашей программой, чтобы увидеть, будет ли это проблемой для вас. Если проблема с памятью, тогда да, вы должны вызвать SubmitChanges, чтобы DataContext мог удалить часть этой информации оттуда.

Тем не менее, есть преимущества и недостатки для вызова SubmitChanges в одном вызове. Допустим, у вас действительно много данных, и вы используете один вызов SubmitChanges. Это блокирует поток, в котором он находится, до его завершения, а в некоторых случаях это может занять очень и очень много времени. Это плохо, если вы хотите сделать что-то, например, возобновить поток, сообщить о ходе выполнения или выполнить другие побочные действия. В этих случаях вам следует периодически вызывать SubmitChanges, чтобы позволить потоку возобновить обработку другой логики, если она есть или требуется.

Если вам действительно все равно, сколько времени это займет, это не повлияет на что-либо еще, тогда достаточно одного вызова SubmitChanges.

В любом случае, SubmitChanges по-прежнему разделяет каждое изменение на отдельную команду и выполняет каждую команду в отдельности. Таким образом, он никогда не выполняет групповые или пакетные команды, он всегда один за другим, независимо от того, выполняете ли вы периодические вызовы SubmitChanges или один вызов.

Страница MSDN на этом поможет вам немного лучше понять SubmitChanges. Есть и другие полезные ресурсы.

Другие вопросы по тегам