Сложная сравнительная работа:
len(set(the_list)) == 1
Использование set
удаляет все повторяющиеся элементы.
EF не является потокобезопасным, поэтому вы не можете использовать Parallel.
Взгляните на Entity Framework и многопоточность
и этот статья .
Это то, что я использую и отлично работаю. Он дополнительно поддерживает обработку исключений ошибок и имеет режим отладки, который значительно облегчает отслеживание вещей вниз
public static ConcurrentQueue<Exception> Parallel<T>(this IEnumerable<T> items, Action<T> action, int? parallelCount = null, bool debugMode = false)
{
var exceptions = new ConcurrentQueue<Exception>();
if (debugMode)
{
foreach (var item in items)
{
try
{
action(item);
}
// Store the exception and continue with the loop.
catch (Exception e)
{
exceptions.Enqueue(e);
}
}
}
else
{
var partitions = Partitioner.Create(items).GetPartitions(parallelCount ?? Environment.ProcessorCount).Select(partition => Task.Factory.StartNew(() =>
{
while (partition.MoveNext())
{
try
{
action(partition.Current);
}
// Store the exception and continue with the loop.
catch (Exception e)
{
exceptions.Enqueue(e);
}
}
}));
Task.WaitAll(partitions.ToArray());
}
return exceptions;
}
. Вы используете его так, как показано ниже, где db - это исходный DbContext и db.CreateInstance ( ) создает новый экземпляр, используя ту же строку соединения.
var batch = db.Set<SomeListToIterate>().ToList();
var exceptions = batch.Parallel((item) =>
{
using (var batchDb = db.CreateInstance())
{
var batchTime = batchDb.GetDBTime();
var someData = batchDb.Set<Permission>().Where(x=>x.ID = item.ID).ToList();
//do stuff to someData
item.WasMigrated = true; //note that this record is attached to db not batchDb and will only be saved when db.SaveChanges() is called
batchDb.SaveChanges();
}
});
if (exceptions.Count > 0)
{
logger.Error("ContactRecordMigration : Content: Error processing one or more records", new AggregateException(exceptions));
throw new AggregateException(exceptions); //optionally throw an exception
}
db.SaveChanges(); //save the item modifications
Немного сложно устранить эту проблему, не зная, каков результат внутреннего исключения, если таковой имеется. Это может быть просто проблемой, связанной с настройкой строки подключения или конфигурации поставщика.
В общем, вы должны быть осторожны с параллельным кодом и EF. Однако то, что вы делаете, должно работать. Один вопрос в моем уме; Выполняется ли какая-либо работа над другим экземпляром этого контекста перед параллелью? Согласно вашему сообщению, вы делаете отдельный контекст в каждом потоке. Это хорошо. Однако часть меня удивляется, если между несколькими контекстами происходит интересное соперничество конструктора. Если вы не используете этот контекст где-либо перед этим параллельным вызовом, я бы предложил попытаться запустить даже простой запрос против контекста, чтобы открыть его и убедиться, что все биты EF запущены перед запуском параллельного метода. Я признаю, что я не пробовал точно , что вы здесь делали, но я сделал близко, и это сработало.