EF 更改跟踪器:集合已修改;枚举操作可能无法执行

本文关键字:操作 枚举 执行 修改 跟踪 集合 EF | 更新日期: 2023-09-27 18:36:05

我在循环访问集合时收到错误。我不会在任何时候更改列表,但它给了我以下"集合已修改;枚举操作可能无法执行。下面的代码显示了我有这个 Parallel.Foreach 的方法。

public void DownloadImages()
        {
            IList<Vehicle> vehicles = _repository.Retrieve().ToList();
            Parallel.ForEach(vehicles, vehicle =>
            {
                IList<VehiclePhoto> vehiclePhotos =
                    vehicle.VehiclePhotos.Where(x => x.ImageStatus == ImageStatus.Inactive).ToList();
                if (vehiclePhotos.Count > 0)
                {
                    Parallel.ForEach(vehiclePhotos, photo =>
                    {
                        using (var client = new WebClient())
                        {
                            try
                            {
                                string fileName = Guid.NewGuid() + ".png";
                                string filePath = _imagePath + "''" + fileName;
                                client.DownloadFile(photo.ImageUrl, filePath);
                                photo.FileName = fileName;
                                photo.ImageStatus = ImageStatus.Active;
                            }
                            catch (Exception)
                            {
                            }
                        }
                    });
                    _repository.Save(vehicle);
                }
            });
        }

这发生在_repository时。保存(车辆)被调用。以下代码将显示保存更改方法。基础。保存更改();是引发错误的地方。

public override int SaveChanges()
        {
            DateTime nowAuditDate = DateTime.Now;
            IEnumerable<System.Data.Entity.Infrastructure.DbEntityEntry<DomainEntity>> changeSet = ChangeTracker.Entries<DomainEntity>();
            if (changeSet != null)
            {
                foreach (System.Data.Entity.Infrastructure.DbEntityEntry<DomainEntity> entry in changeSet)
                {
                    switch (entry.State)
                    {
                        case EntityState.Added:
                            entry.Entity.Created = nowAuditDate;
                            entry.Entity.Modified = nowAuditDate;
                            break;
                        case EntityState.Modified:
                            entry.Entity.Modified = nowAuditDate;
                            break;
                    }
                }
            }
            return base.SaveChanges();
        }

对此有什么想法吗?

编辑:我正在尝试修复上述错误,并在DownloadImages方法中更改了几行代码。这些更改如下所示:

而不是

IList<Vehicle> vehicles = _repository.Retrieve().ToList(); 

我使用了变量

var vehicles = _repository.Retrieve().AsParallel(); 

而不是

IList<VehiclePhoto> vehiclePhotos =
                        vehicle.VehiclePhotos.Where(x => x.ImageStatus == ImageStatus.Inactive).ToList();

我使用了变量

var  vehiclePhotos =
                            vehicle.VehiclePhotos.Where(x => x.ImageStatus == ImageStatus.Inactive).AsParallel();

当我尝试再次运行代码时。它给了我一个不同的错误:错误如下:

在标题中它说

System.Data.Entity.Infrastructure.DbUpdateException

但在内部异常

System.Data.Entity.Core.UpdateException

当分配给命令的连接位于挂起的本地事务中时,ExecuteNonQuery 要求命令具有事务。 命令的事务属性尚未初始化。

EF 更改跟踪器:集合已修改;枚举操作可能无法执行

发生这种情况是因为您正在迭代vehicles并且循环中的代码正在更改枚举vehicles的元素。此外,循环vehiclePhotos并更改其元素。

我通常通过使用显式for循环来解决此问题,即:

for(var i = 0; i < vehicles.Count; i++)
{
    var vehicle = vehicles.ElementAt(i);
    // process vehicle
}

但是,如果您需要使用 Parallel.ForEach ,您可以尝试创建一个长度为 vehicles.Count 的整数数组,迭代该数组并将其用作vehicles的索引。