01 |
Ошибка возникает при попытке осуществить запись изменений в БД — db.SaveChanges(), в случаях, подобных следующему примеру: |
02 | VB.NET |
1 Dim oldContracts As IEnumerable(Of Contract) = db.Contracts.Where(Function(c) c.ContrID = id) For Each oldContract As Contract In oldContracts db.SaveChanges() Next |
03 |
Оказывается, что транзакцию блокирует цикл перебора: |
04 | VB.NET |
1 For Each oldContract As Contract In oldContracts |
05 |
Дело в том, что функция Where(Function()…) возвращает результат типа Linq.IQueryable(), который создает транзакцию, которая в свою очередь остается открытой на все время исполнения запроса — на весь цикл перебора. А вызов метода db.SaveChanges() пытается открыть новую транзакцию, при открытой предыдущей и это вызывает исключение. Чтобы «завершить» открытую транзакцию необходимо привести результат к «конечному» типу, например Array или List(Of …). Для этого необходимо изменить код: |
06 | VB.NET |
1 Dim oldContracts As Contract() = db.Contracts.Where(Function(c) c.ContrID = id).ToArray Dim oldContracts As List(Of Contract) = db.Contracts.Where(Function(c) c.ContrID = id).ToList Dim lstContracts As IEnumerable(Of Contract) = db.Contracts.Where(Function(c) c.ContrID = id) For Each oldContract As Contract In oldContracts |
07 |
Похожие запросы:
|
Using Entity Framework in .NET I want to loop through a list of items returned from the database and make updates.
var qry = (from c in DBEntities.Customer select c);
foreach (Object item in qry)
{
item.FirstName = ....
... etc, other code here
DBEntities.SaveChanges();
}
According to : http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/8a337036-d288-48d4-80d4-89e5a51eddd9?ppud=4 S Hargroves suggests converting to a IList and that is the solution.
Haven’t tried that, I’m sure it will work, but even it works, I want to know why I can’t update the item during the loop? This is occuring on my local development environment with no other users hitting the database.
Thanks …
Jon Seigel
12.2k8 gold badges57 silver badges92 bronze badges
asked Feb 18, 2010 at 0:12
1
When you update the database using SaveChanges on a query, the query is invalidated. The result set may have been changed by the update you performed.
By using ToList
, you are triggering the execution of the query and bringing all the results from the database into memory. Your in-memory list is now concrete and not concerned with being a query anymore.
Because Object Queries use IEnumerable
, its not ok to do something that modifies the list in a foreach.
I also believe this code would fail for the same basic reasons:
List<int> numbers = new List<int>() { 1,2,3,4,5,6};
foreach(var num in numbers)
numbers.Remove(num); //Invalidates the Enumerator being used in the foreach
answered Feb 17, 2011 at 20:30
TilendorTilendor
47.9k17 gold badges51 silver badges58 bronze badges
2
I would agree with making the var a list.
Then in your foreach,instead of using Object item in qry, use Customer customer in qry. In that scenario you are really working with customer objects not just objects. In most cases you wouldn’t want to call SaveChanges() in a foreach because it is going to execute an update command on the server each time that is executed. If you do it after the foreach it will make one batch of calls to the database and perform a lot nicer.
My suggested pseudo code looks something like
var customers = (from c in DBEntities.Customer select c).ToList<Customer>();
foreach (Customer customer item in customers)
{
customer.FirstName = ....
... etc, other code here
}
DBEntities.SaveChanges();
answered Feb 18, 2010 at 0:46
awright18awright18
2,2552 gold badges23 silver badges22 bronze badges
Ok I have ran into the same issue. Right now I do not have a million records only about 20K, but the table I want to processes stores images so when processing the table to a List takes way too long, Even on a desktop app.
I have been using LinqToSql since it came out and it works fine in LinqToSql, so I was kinda pissed when I seen it’s not working in Entity. And it’s stupid Microsoft didn’t make it work in Entity, but here is the work around. Make 2 Context objects. One for the list and one for the updates as follows.
entityList _imgList = new entityList();
entityList _imgSave = new entityList();
// Now the 1st time I did this I got the whole record like follows.
var _imgList = _imgList.Images.where( i=> i.NotProcessed == false);
foreach(Images _img_p in imgList)
{
if(something)
{
Images _img = _imgSave.Single(i=> i.ID == _img_p.ID);
_img.NotProcessed == true;
imgSave.SaveChanges();
}
}
imgList.dispose();
imgSave.dispose();
// After i verified this worked I figured why do I need to whole record to loop though so I changed it to just get the ID then process my loop as follows, and it works great.
var _imgIds = _imgList.Images.where( i=> i.NotProcessed == false ).select(i=>i.ID);
foreach(long _imgID in imgList)
{
Images _img = _imgSave.Single(i=> i.ID == _imgID);
if(something)
{
_img.NotProcessed == true;
imgSave.SaveChanges();
}
}
imgList.dispose();
imgSave.dispose();
You can see more at my Blog Post (ASP.Net Help Blog)
answered Jun 19, 2011 at 17:51
1
Thanks for the recommendation on SavingChanges after loop, I hadn’t thought of that. However I’ve got to process over 1 Million records, this is not all that much, but there is some processing that will be performed during each loop. So I’m a little concerned that it will take quite a lot of time to loop the 1 Million records updating the information and then take a while to post the changes.
I also know that the EntityFramework probably isn’t the best approach, but I’m interested in learning features and limitations of Entity Framework.
Also just to note the var list actually returns a ObjectQuery of Customer type. So the foreach loop can actually be written as the above using Customer variable data type even without converting to a list.
Again my question that I’d like to know is why can’t I post a change in the same context object (DBEntities) during the loop?
answered Feb 18, 2010 at 4:25
CWinKYCWinKY
3352 gold badges5 silver badges10 bronze badges
1
- Remove From My Forums
Не правильно записываю
-
Вопрос
-
Добрый день!
Подскажите пожалуйста где моя ошибка?
var list = db.OrdersList.Where(f => f.Kod_orders == 113); foreach (OrdersList t in list) { if (t.Count.ToString() != Request["value_" + t.Id_order]) { var change = db.OrdersList.SingleOrDefault(g => g.Id_order ==3); change.Count = 5; db.SaveChanges(); return RedirectToAction("index", "Home", new { id = "Work_" + Request["value_" + t.Id_order]+"_ID_"+ t.Id_order }); }
В итоге получаю ошибку при сохранении бд:
Ошибка при запуске транзакции в соединении поставщика. Подробные сведения см. во внутреннем исключении.
Где я ошибся?
Ответы
-
Спасибо, что откликнулись. Мне правда нужно было сделать не для одно случая, а для целого ряда. Тот код просто был для проверки. Но к сожалению не помог. Вышел из ситуации подругому. Итак вот код контроллера:
var list = db.OrdersList.Where(f => f.Kod_orders == 113); foreach (OrdersList t in list) { if (t.Count.ToString() != Request["value_" + t.Id_order]) { ProdModel.ChangeCount(t.Id_order, Request["value_" + t.Id_order]); } } return RedirectToAction("Detail", "Manage", new {id = 113});
И модель:
public void ChangeCount(int id, string NewCount) { var g = db.OrdersList.Single(d => d.Id_order == id); int f = Convert.ToInt32(NewCount); g.Count = f; db.SaveChanges(); }
После этого все отлично заработало
-
Помечено в качестве ответа
22 августа 2012 г. 9:43
-
Изменено
ZEONE
22 августа 2012 г. 9:48
-
Помечено в качестве ответа
Эта статья относится к следующим пространствам имен платформа .NET Framework Microsoft Платформа .NET Framework для занятий:
-
System.Data
-
System.Data.OleDb
-
System.Data.SqlClient
Проблемы
При использовании поставщика Microsoft OLE DB для SQL Server (OLEDBSQL) в ADO.NET при попытке запустить несколько транзакций в сеансе вы получаете следующее сообщение об ошибке:
System.Data.OleDb.OleDbException: не удается запустить дополнительные транзакции в этом сеансе
Причина
По проекту поставщик OLE DB для SQL Server не допускает вложенных транзакций.
Дополнительная информация
Действия для воспроизведения поведения
-
Начните Microsoft Visual Studio .NET.
-
Создайте проект Windows приложения в Visual Basic .NET. По умолчанию создается форма 1.
-
Дважды щелкните Форму1, чтобы открыть окно Код.
-
Замените код в форме 1 следующим кодом:
Imports System.Data
Imports System.Data.OleDb
Imports System.Data.SqlClientPublic Class Form1
Inherits System.Windows.Forms.FormDim cn As New OleDb.OleDbConnection()
Dim cmd As New OleDb.OleDbCommand()
Dim mycmd As New OleDb.OleDbCommand()#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()'This call is required by the Windows Form Designer.
InitializeComponent()'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub'Required by the Windows Form Designer
Private components As System.ComponentModel.Container'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Name = "Form1"
Me.Text = "Form1"End Sub
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
cn.ConnectionString = "Provider=SQLOLEDB;Data Source=YourServer;" & _
"Initial Catalog=pubs;User ID=YourUserID;Password=YourPassword"
cn.Open()
cmd.Connection = cn
mycmd.Connection = cn
cmd.CommandText = "Insert into stores (stor_id) values('9876')"
Dim myTrans As OleDb.OleDbTransaction
myTrans = cn.BeginTransaction(IsolationLevel.ReadCommitted)cmd.Transaction = myTrans
Try
cmd.ExecuteNonQuery()myTrans.Begin()
myTrans.Commit()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End TryEnd Sub
End Class -
Измените строку подключения, соответствующую вашей среде.
-
Запустите приложение. Обратите внимание, что вы получили сообщение об ошибке, которое указано в разделе «Симптомы».
Ссылки
Для получения дополнительных сведений щелкните номер статьи ниже, чтобы просмотреть статью в базе знаний Майкрософт:
306649 PRB: ошибка при внедрении вложенной транзакции с поставщиком OLE DB для поставщика SQL.
Нужна дополнительная помощь?
Нужны дополнительные параметры?
Изучите преимущества подписки, просмотрите учебные курсы, узнайте, как защитить свое устройство и т. д.
В сообществах можно задавать вопросы и отвечать на них, отправлять отзывы и консультироваться с экспертами разных профилей.
Произошла ошибка при запуске транзакции в соединении провайдера. Смотрите внутреннее исключение для деталей
Это мое кодирование. Он показывает ошибку, как
Произошла ошибка при запуске транзакции при подключении к провайдеру. Подробнее см. Внутреннее исключение.
DemoEntities db = DemoEntities.CreateNewDemoEntity();
var query = (from f in db.Product_Table
where f.ReportID == reportID && f.StateID == stateID
select f);
foreach(var q in query)
{
Custom_Search_Transformation cst = new Custom_Search_Transformation()
{
CustomerID = customerID,
StateID = stateID,
FullProductID = q.FullProductID
};
db.Custom_Search_Transformation.AddObject(cst);
db.SaveChanges();
}
23 янв. 2014, в 12:12
Поделиться
Источник
db.SaveChanges();
должен выходить за пределы цикла foreach
:
DemoEntities db = DemoEntities.CreateNewDemoEntity();
var query = (from f in db.Product_Table
where f.ReportID == reportID && f.StateID == stateID
select f);
foreach(var q in query)
{
Custom_Search_Transformation cst = new Custom_Search_Transformation()
{
CustomerID = customerID,
StateID = stateID,
FullProductID = q.FullProductID
};
db.Custom_Search_Transformation.AddObject(cst);
}
db.SaveChanges();
Golda
23 янв. 2014, в 13:02
Поделиться
Сделайте свои списки Queryable в .ToList(), он должен работать нормально.
zaza
15 апр. 2015, в 21:42
Поделиться
Как бы то ни было, это самая глупая структура, кажется, что вы не можете циклически преобразовывать объекты Entities в то же время, что вы хотите их сохранить. Итак, что вы должны сделать, это сделать один объект Entitie для вашего цикла, а другой — для вашего обновления. вы можете использовать SaveChanges(); в вашем цикле нет никакой проблемы.
marc.platvoet
17 окт. 2014, в 12:43
Поделиться
Ещё вопросы
- 0два вызова timer_settime выдают ошибку
- 0301 Перенаправления после копирования установки Magento
- 0Реализация класса List Ошибка выделения памяти с указателем
- 0значение увеличения прогресса не работает с процентами
- 0Слайдер Jquery не работает на iPad отлично работает в браузере
- 0Динамически добавленный атрибут управления отображается как «элементы управления =» вместо элементов управления
- 1C # Reflection: В чем разница между FieldInfo.SetValue () и FieldInfo.SetValueDirect ()?
- 0простое исключение в JavaScript, чтобы код не работал
- 0Как реализовать PHP в HTML-файл
- 0получать события из базы данных и размещения в режиме просмотра календаря (Android)
- 0img и вертикальное выравнивание текста
- 0SELECT в INSERT Значения Ошибка
- 0Предоставление доступа нескольким пользователям к состоянию сеансов на AngularJs (JHipster Project)
- 1блоки инициализации в полиморфизме
- 0C ++ STL и библиотеки DLL
- 1Получить совпадающее значение регулярного выражения
- 1Есть ли способ заставить модифицированную / gson разыграть двойную временную метку на длинную?
- 1Определить состояние сети и загрузить видео данные из фона, когда приложение убито в Android пирог (API 28)
- 0Как скрыть URL при печати страницы с помощью JavaScript или JQuery
- 0MySQL SELECT, если нет более новой записи
- 0Mysql выберите запрос не работает должным образом
- 0Объединить 2 ассоциативных массива путем сопоставления значения подмассива?
- 0Hibernate: Можно ли использовать Like и In вместе в Named Query?
- 0Как правильно получить ресурсы с условно-инициализированными объектами в C ++?
- 0jQuery при загрузке анимированного изображения слева направо
- 0codeigniter получить количество num_rows
- 1js Дата изменения 10 октября (BST) [копия]
- 0MySQL запрос поиска в левом соединении, которые имеют условие, связанное со столбцом
- 0Нет пробела между кнопками «на следующей строке»
- 0JQuery загрузить страницу в диалог
- 0Angularjs Многомерный массив и два относительных поля выбора
- 0Отображение / скрытие div в зависимости от значения Select
- 1Назначение и вызов свойств объекта внутри другого объекта
- 1Аутентификация Firebase createUserWithEmailAndPassword не выполняется на физических устройствах с переменной для электронной почты
- 0Пользовательский размер фотоснимка Tumblr с бесконечной прокруткой
- 1Как я могу показать сообщение об ошибке в окне сообщения в C # исключения SQL (уникальный идентификатор) в 3-уровневом приложении?
- 1Tokenize.detect_encoding (readline) есть только в python3?
- 1Совместимость с Android + FTDI FT232H
- 0Соответствие строк в MySQL: 1 изменено: 0 предупреждений: 0 для столбца даты
- 1getAdapter (). notifyDataSetChanged () не изменяет базу данных для повторного просмотра
- 1Шаг через сторонний код в Eclipse
- 1Не удалось загрузить ресурс при загрузке изображения
- 1Найти совпадающее содержимое и длину массива в одном внутреннем свойстве
- 0В чем разница между передачей счетчика цикла или объявления диапазона потоку по ссылке?
- 0Как удалить следующие выделенные элементы из DOM?
- 0Как получить экземпляр выбранного в данный момент li с помощью JQuery
- 0Как передать событие, вызванное jQuery, в функцию
- 0Абсолютное позиционирование по отношению к родителю
- 1Замена всех элементов, кроме последнего, в определенных строках 2D-массива
- 0Jquery не срабатывает, если оператор для определенных значений