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);
context.Entry(entity).State = EntityState.Modified;
}
return entity;
}
This is my damagecore
public static Result NewDamage(Context ctx, CarDamage _newCarDamage)
{
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;
}
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;
}
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);
FillDataOnForm(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;
}
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
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
{
context.Set<T>().Attach(entity);
context.Entry(entity).State = EntityState.Modified;
}
return entity;
}