#c# #.net #frameworks #entity
#c# #.net #фреймворки #сущность
Вопрос:
В настоящее время у нас есть производственное приложение, которое работает как служба Windows. Много раз это приложение попадет в цикл, который может занять несколько часов. Мы используем Entity Framework для .net 4.0 для нашего доступа к данным.
Я ищу подтверждение того, что если мы загрузим новые данные в систему после инициализации этого цикла, это не приведет к добавлению элементов в сам цикл. Когда цикл инициализируется, мы ищем данные «по состоянию» на этот момент. Хотя я относительно уверен, что это будет работать точно так же, как использование ADO и выполнение цикла над данными (цикл циклически обрабатывает только данные, которые присутствовали во время инициализации), я ищу подтверждение для коллег.
Заранее спасибо за вашу помощь.
// обновление: вот несколько примеров кода на c # — вопрос тот же, изменится ли перечисление, если в таблицу, которую запрашивает EF, будут добавлены новые элементы?
IEnumerable<myobject> myobjects = (from o in db.theobjects where o.id==myID select o);
foreach (myobject obj in myobjects)
{
//perform action on obj here
}
Комментарии:
1. Джефф, ты не можешь сказать с уверенностью, это зависит от того, как был написан код, а не от фреймворка. Большинство (не все) программисты пишут пакетные процессы для запроса всех данных в начале процесса. Однако возможно (хотя и маловероятно), что программа запрашивает базу данных на протяжении всей операции. Окончательный ответ требует прохождения кода.
Ответ №1:
Это зависит от вашей точной реализации.
После выполнения запроса к базе данных результаты запроса не изменятся (при условии, что вы не используете отложенную загрузку). Чтобы убедиться в этом, вы можете удалить контекст после получения результатов запроса — это эффективно «перерезает связь» между полученными данными и этой базой данных.
Отложенная загрузка может привести к смешиванию «исходных» и «новых» данных; однако, как только данные будут получены, они станут фиксированным снимком и не будут подвержены обновлениям.
Вы упоминаете, что это длительный процесс; что подразумевает, что может быть задействован очень большой объем данных. Если вы не можете полностью получить все данные, подлежащие обработке (из-за ограничений памяти или других узких мест), то вы, вероятно, не сможете гарантировать, что работаете с исходными данными. Результаты не фиксируются до тех пор, пока не будет выполнен запрос, и любые обновления до выполнения запроса будут отображаться в результатах.
Комментарии:
1. Это был ответ, мне нужно посмотреть, делает ли реализация IEnumerable то же самое, что и выполнение ToList(). Поскольку отложенная загрузка включена по умолчанию в EF
2. Я также нашел подтверждение того, что реализация IEnumerable устраняет отложенную загрузку и загружает результаты в память. Итак, ответ заключается в том, что с кодом, который у меня есть выше, коллекция останется нетронутой.
3. да, как правило
IQueryable
, это интерфейс, с которым вам нужно быть наиболее осторожным
Ответ №2:
Я думаю, что лучше всего изменить логику вашего приложения таким образом, чтобы, когда логика «цикла» определяла, следует ли ей выполнять другое взаимодействие или выходить, вы воспользовались возможностью загрузить вновь добавленные элементы в список. смотрите псевдокод ниже:
var repo = new Repository();
while (repo.HasMoreItemsToProcess())
{
var entity = repo.GetNextItem();
}
Дайте мне знать, если это имеет смысл.
Комментарии:
1. Привет, спасибо за это предложение, но меня беспокоит то, что я не хочу, чтобы новые объекты обрабатывались. Ваш код был бы идеальным, если бы мне нужно было проверять наличие новых объектов, а затем вставлять их. Проблема в том, что я не уверен, как Entity Framework работает при циклическом выполнении перечисления. Если он квалифицирует коллекцию в каждом цикле или просто поддерживает коллекцию в том виде, в каком она была изначально инициализирована.
2. понял. он преобразует все, что вы пишете в Linq, в SQL-запрос, поэтому я бы предположил, что каждый раз, когда вы выполняете запрос в контексте, он не «прослушивает» добавление новых строк.
3. (вот почему я предложил добавить свой собственный уровень абстракции за пределами EF)
Ответ №3:
Самый простой способ гарантировать, что это произойдет — если сами данные не слишком большие — это преобразовать данные, которые вы извлекаете из базы данных, в список <> , например, что-то вроде этого (случайно извлеченный из моего текущего проекта):
var sessionIds = room.Sessions.Select(s => s.SessionId).ToList();
А затем выполните итерацию по списку, а не по IEnumerable<> , который в противном случае был бы возвращен. Преобразование его в список запускает перечисление, а затем отправляет все результаты в память.
Если данных слишком много, чтобы поместиться в память, и вам нужно придерживаться IEnumerable<> , то ответ на ваш вопрос зависит от различных настроек базы данных и подключения.
Ответ №4:
Я бы сделал снимок идентификаторов для обработки — быстро и в виде транзакции — а затем обработал этот список так, как вы делаете сегодня.
В дополнение к достижению цели не изменять образец в середине потока, это также дает вам возможность расширить ваше решение для отслеживания состояния каждого элемента по мере его обработки. Для длительно выполняющегося процесса это может быть очень полезно для отчетов о ходе выполнения, перезапуска / повторных попыток и т. Д.