更新时出现奇怪的错误 [英] Strange error on Updating

查看:100
本文介绍了更新时出现奇怪的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

各位大家好!



首先抱歉我的英语不好。

我是一名初学程序员,我有以下问题。



使用EF和通用存储库,我可以进行插入和删除问题。

当我对同一个数据库和同一个对象进行更新时调用此问题。



错误信息如下:

System.InvalidOperationException

收藏被修改;枚举操作可能无法执行。



我做了一些研究,但我无法解决问题是什么......

奇怪的是我使用与select /或insert相同的上下文(因此集合必须相同)。



有人有想法吗?



非常感谢提前!



代码:





这是通用存储库中的方法



Hello everybody!

First of all sorry about my bad English.
I am a starting programmer and I have following problem.

With EF and a generic repository I can do an Insert and Delete without any problem.
The problem is invoked when I do an update on the same database and same object.

The error message is the following:
System.InvalidOperationException
Collection was modified; enumeration operation may not execute.

I have done some research but I can't solve of figuring out what is the problem...
The strange thing is that I use the same context as the select / or insert (so the collection must be the same).

Has anyone an idea?

Many thanks in advance!

the code:


this is the method in the generic repository

public static T AddOrUpdate<T>(this DbContext context, T entity)
           where T : class
       {
           if (context == null) throw new ArgumentNullException("context");
           if (entity == null) throw new ArgumentNullException("entity");

           if (IsTransient(context, entity))
           {

               context.Set<T>().Add(entity);
           }
           else
           {
               context.Set<T>().Attach(entity);  //here I get the error
               context.Entry(entity).State = EntityState.Modified;
           }
           return entity;
       }





这是我的伤害核心





This is my damagecore

public static Result NewDamage(Context ctx, CarDamage _newCarDamage)//Damage _newDamage)
        {
            
            
            GenericRepository<CarDamage> carCamageRepo = new GenericRepository<CarDamage>(ctx);
            carCamageRepo.AddOrUpdate(_newCarDamage);
            
            ctx.SaveChanges();
            
            return null;
        }









按钮背后的代码







code behind the button

private void save_Click(object sender, RoutedEventArgs e)
     {
         double invAmount;
         if (NoEmptyFieldsCheck() == false)
         {
             MessageBox.Show("Gelieve alle velden in te vullen", "Schade", MessageBoxButton.OK, MessageBoxImage.Warning);
             return;
         }
         if (DamageOverviewCheck() == false)
         {
             MessageBox.Show("Gelieve minstens 1 schade onderdeel toe te voegen", "Schade", MessageBoxButton.OK, MessageBoxImage.Warning);
             return;
         }
         if (Double.TryParse(invoiceAmount.Text, out invAmount)== false)
         {
             MessageBox.Show("Geef een geldig factuurbedrag","Schade", MessageBoxButton.OK, MessageBoxImage.Warning);
             return;
         }

        // Damage newDamage = new Damage();

        // CarDamage newCarDamage = new CarDamage() { Car = (Car)carComboBox.SelectedItem, ActualValue= true };
         carDamage.Car = (Car)carComboBox.SelectedItem;
         carDamage.ActualValue = true;

         newDamage.DamageDate = damageDate.SelectedDate ?? DateTime.Today;
         newDamage.DamageState = (DamageState)damageStateComboBox.SelectedItem;
         newDamage.DamageCauser = damageCauser.Text;
         newDamage.InvoiceAmount = (float)invAmount;
         newDamage.PaymentFranchiseDriver = paymentFranchiseDriver.IsChecked.Value;
         newDamage.PaymentOk = paymentOk.IsChecked.Value;
         newDamage.DamageOverview = damageOverview;

         if (accident.IsChecked == true)
         {
             Accident newAccident = new Accident();
             newAccident.AccidentFileDate = fileDate.SelectedDate ?? DateTime.Today;
             newAccident.FileState = (FileState)fileStateComboBox.SelectedItem;
             newAccident.AccidentDescription = accidentDescriptionTxtBox.Text;
             newDamage.Accident = newAccident;

         }

         if (files.Count > 0)
         {


             foreach (var file in files)
             {
                 Document doc = new Document();

                 string fileExtention = Path.GetExtension(file);
                 string fileName = Path.GetFileNameWithoutExtension(file);
                 string originalFilePath = Path.GetFullPath(file);
                 doc.FileDestination = @"C:\Users\Jeffry\Desktop\document.carma\" + doc.DocumentID + fileExtention;

                 doc.OriginalFileName = fileName;
                 doc.AdditionDate = DateTime.Today;
                 File.Copy(originalFilePath, doc.FileDestination);





             }
             newDamage.Document = docList;
         }

         carDamage.CarID = (int)carComboBox.SelectedValue;
         carDamage.ActualValue = true;
         carDamage.Damage = newDamage;
         DamageCore.NewDamage(mainWindow.ctx, carDamage);

         id = newDamage.DamageID; //getting id of last added damage (needed to go to documents for getting right documents)

     }







已添加15/04/2014





ObjectID传递给构造函数




Added 15/04/2014


ObjectID is passed to constructor

private void viewDetail_Click(object sender, RoutedEventArgs e)
       {
           CarDamage carDamage = (CarDamage)damageLV.SelectedItem;
           DamagePage damagePage = new DamagePage(mainWindow, carDamage.DamageID);
           mainWindow.MainFrame.Navigate(damagePage);
       }





页面构造函数



Constructor of the page

public DamagePage(MainWindow main, int damageId)
       {
           mainWindow = main;
           mainWindow.SetTitle("Detail schade");
           InitializeComponent();
           AddData();
           carDamage = DamageCore.GetDamage(mainWindow.ctx, damageId);
           //carDamage.CarDamageID = damageId;
           FillDataOnForm(carDamage);
       }







代码我获取CarDamage对象并填写表格...由构造函数调用






Code where i get CarDamage object and fill the form... is invoked by the constructor

private void FillDataOnForm(CarDamage carDamage)
      {
          damageDate.SelectedDate = carDamage.Damage.DamageDate;
          carComboBox.SelectedValue = carDamage.CarID;
          damageStateComboBox.SelectedValue = carDamage.Damage.DamageStateID;
          damageCauser.Text = carDamage.Damage.DamageCauser;
          invoiceAmount.Text = carDamage.Damage.InvoiceAmount.ToString("0.00");

          paymentFranchiseDriver.IsChecked = carDamage.Damage.PaymentFranchiseDriver;
          paymentOk.IsChecked = carDamage.Damage.PaymentOk;
          accident.IsChecked = false;
          if (carDamage.Damage.AccidentID != 0)
          {
              accident.IsChecked = true;
              fileDate.SelectedDate = carDamage.Damage.Accident.AccidentFileDate;
              fileStateComboBox.SelectedValue = carDamage.Damage.Accident.FileStateID;
              accidentDescriptionTxtBox.Text = carDamage.Damage.Accident.AccidentDescription;
          }
          damageOverview = carDamage.Damage.DamageOverview;

          damagesLV.ItemsSource = null;
          damagesLV.ItemsSource = damageOverview;
          docList = carDamage.Damage.Document;
          id = carDamage.DamageID;



      }







更新时间17/04/2014



通用更新




Update 17/04/2014

Generic update

public void Update(T entity)
        {
            var entry = _context.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                _context.Set<T>().Attach(entity);
                entry = _context.Entry(entity);
            }
            entry.State = EntityState.Modified;
        }





update 23/04/2014



我仍然有同样的问题...



这是我的添加或更新方法......(也不起作用...... :()



update 23/04/2014

I still have the same problem...

Here is my add or update method... (which also doesn't work... :( )

public static T AddOrUpdate<T>(this DbContext context, T entity)
            where T : class
        {
            if (context == null) throw new ArgumentNullException("context");
            if (entity == null) throw new ArgumentNullException("entity");
            
            if (IsTransient(context, entity))
            {
                
                context.Set<T>().Add(entity);
            }
            else
            {
                // original
                context.Set<T>().Attach(entity);

// here i Get an error... and i don't know why...

//errormessage: Collection was modified; enumeration operation may not execute !!!!!!!!???????


                context.Entry(entity).State = EntityState.Modified;


                //test
                //context.Entry<T>(entity).State = EntityState.Modified;
                //context.Entry(entity).State = EntityState.Modified;
            }
            return entity;
        }

推荐答案

1.在更新的情况下,实体必须具有其主键的有效值,所以EF可以在DB中找到它然后将它附加到当前上下文。



2.首先,你必须调试代码并检查在方法 AddOrUpdate 的乞讨上面的第1点,如果来的数据不正确,你应该在调用的地方做更改!



3.你的 carDemage 每次创建对象之前都要调用 AddOrUpdate 您的 save_Click 方法中的方法,如下一个代码:

1.In the case of update the entity must have valid value(s) for its "primary key", so the EF to can find it in the DB and then to attach it to the current context.

2.So first you have to debug your code and check the 1st point above at the begging of method AddOrUpdate, and if the data that come are not OK, you should do changes at the place of invocation!

3.Your carDemage object should be created each time before to invoke AddOrUpdate method in your save_Click method like in the next code:
CarDamage carDemage = new CarDemage();
carDemage.ID = ...; // must be set!
carDamage.ActualValue = ... // set the other properties!
//.. 



4.您正在尝试附加 CarDamage 对象 DbContext 对象,但该对象已附加到此EF上下文。因此解决方案是只搜索此对象(通过其ID),然后设置其更改的属性,最后 SaveChanges()


4.You are trying to attach an CarDamage object to your DbContext object, but the object is already attached to this EF context. So the solution is to just search for this object (by its ID), then set its changed properties, and finally SaveChanges().


这篇关于更新时出现奇怪的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆