В SaveChanges
используется SqlCommand. Если имя длиннее, чем ограничение базы данных, оно будет молча усечено, поэтому не будет выдано никакой ошибки.
BulkInsert
использует SqlBulkCopy
, если имя длиннее, чем предел базы данных, будет выдано сообщение об ошибке.
Это объясняет, почему вы получаете ошибку в одном случае, а не в другом.
SqlBulkCopy не вызывает эту ошибку для развлечения, поэтому я бы дважды проверил вашу длину с вашим размером столбца.
char(xyz)
и в конце есть место? .NET Fiddle поддерживают пакеты Entity Framework
и NuGet
. Так что, если бы вы могли воспроизвести это онлайн, можно было бы точно сказать, почему это происходит.
Пример: https://dotnetfiddle.net/35mQ0W
Вам действительно нужно делать это в цикле foreach
?
Это даст те же результаты, что и ваши примеры, т. Е. Удалит все элементы из списка вверх до первого элемента, который соответствует условию (или удаляю все элементы, если ни один из них не соответствует условию).
int index = Os.FindIndex(x => x.cond);
if (index > 0)
Os.RemoveRange(0, index);
else if (index == -1)
Os.Clear();
Это хорошо обсуждается в Удаление элементов из списка во время итерации по нему .
Они предлагают:
for(int i = 0; i < count; i++)
{
int elementToRemove = list.Find(<Predicate to find the element>);
list.Remove(elementToRemove);
}
Если вы знаете, что ваш список не очень большой, вы можете использовать
foreach (Type o in new List<Type>(Os))
....
, который создаст временную копию списка. Тогда ваш вызов remove () не будет мешать итератору.
Обновление: добавлено для полноты картины
Как несколько ответили, вы не следует изменять коллекцию при ее повторении с помощью GetEnumerator () (пример foreach
). Фреймворк не позволяет вам сделать это, создав исключение. Типичным вариантом решения этого является повторение «вручную» с для
(см. Другие ответы). Будьте осторожны со своим индексом, чтобы не пропускать элементы или повторно оценивать один и тот же дважды (используя i -
или итерацию в обратном направлении).
Однако для вашего конкретного случая мы можем оптимизировать операции удаления ... исходный ответ ниже.
Если вы хотите удалить все элементы, пока один из них не будет соответствовать заданному условию (это то, что делает ваш код), вы можете сделать это:
У меня только что возникла проблема с моей библиотекой анализа. Я пробовал это:
for (int i = 0; i < list.Count; i++)
{
if (/*condition*/)
{
list.RemoveAt(i);
i--;
}
}
Это довольно просто, но я не придумал ни одной точки останова.
Никогда не следует удалять что-либо из коллекции, которую вы повторяете, находясь внутри цикла foreach. По сути, это похоже на пиление ветки, на которой вы сидите.
Используйте альтернативу while. Это путь.
Я программист на Java, но работает что-то вроде этого:
List<Type> Os;
List<Type> Temp;
...
foreach (Type o in Os)
if (o.cond)
Temp.add(o);
Os.removeAll(Temp);
Вы можете перебирать список в обратном направлении:
for (int i = myList.Count - 1; i >= 0; i--)
{
if (whatever) myList.RemoveAt(i);
}
В ответ на ваш комментарий о желании выйти, когда вы обнаружите элемент, который НЕ удаляете, просто использование цикла while будет лучшее решение.
Я бы попытался найти индекс первого элемента, который не удовлетворяет предикату и сделайте RemoveRange (0, index) на нем. По крайней мере, должно быть меньше вызовов Remove.
Посмотрите на Enumerable.SkipWhile ()
Enumerable.SkipWhile( x => condition).ToList()
Обычно отсутствие изменения списка значительно упрощает жизнь. :)
Я знаю, что вы просили о чем-то другом, но если вы хотите условно удалить группу элементов, вы можете использовать лямбда-выражение:
Os.RemoveAll(o => !o.cond);