Reputation: 4040
Does anyone know what the proper way of adding records using loops?
I have a system that handles Inventory, Currently I need to be able to Mass Create inventory as creating 50-100 identical items with different ID's would be tedious, What I did was create a MassCreate viewmodel that would essentially take a StartID and an EndID and a base Inventory Class and in the controller loop through the difference between those two ID's and create a record
The ViewModel isn't an issue and passes the data just fine:
public class MassCreateInventoryViewModel
{
public Inventory InventoryBase { get; set; }
public int StartID { get; set; }
public int EndID { get; set; }
public IEnumerable<SelectListItem> Products { get; set; }
}
I read somewhere that the db.SaveChanges()
should be outside of the loop as it should only be called once:
for (int inventoryID = viewModel.StartID; inventoryID <= viewModel.EndID; inventoryID++)
{
Inventory newInventory = new Inventory
{
InventoryID = inventoryID,
ProductID = viewModel.InventoryBase.ProductID,
DateEdited = DateTime.Now,
EditedByUserID = WebSecurity.CurrentUserId,
CustomProperties = viewModel.InventoryBase.CustomProperties
};
Database.Inventories.Add(newInventory);
if (newInventory.CustomProperties != null && newInventory.CustomProperties.Any())
{
foreach (CustomDataType dt in newInventory.CustomProperties.Select(x => x.DataType).ToList())
{
Database.Entry(dt).State = EntityState.Unchanged;
}
}
}
Database.SaveChanges();
}
But when I try looping, it stores the first record just fine then throws a Collection was modified; enumeration operation may not execute.
Exception. When I include the Database.SaveChanges()
after the Add
method, it throws A The property 'InventoryID' is part of the object's key information and cannot be modified.
error.
The InventoryID is the Key
in this table but has been set so that I can input my own ID.
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Inventory ID")]
public new int InventoryID { get; set; }
The Custom Property is split into two models, the first being the base class.
public class CustomProperty
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CustomPropertyID { get; set; }
public int CustomDataTypeID { get; set; }
[ForeignKey("CustomDataTypeID")]
public CustomDataType DataType { get; set; }
public string PropertyValue { get; set; }
}
and the second being the model thats mapped to the database:
[Table("CustomInventoryProperty")]
public class CustomInventoryProperty : CustomProperty
{
public int InventoryID { get; set; }
[ForeignKey("InventoryID")]
public virtual Inventory Inventory { get; set; }
}
Upvotes: 0
Views: 249
Reputation: 9155
Replace your for loop with this:
var dateEdited = DateTime.Now;
for (int inventoryID = viewModel.StartID; inventoryID <= viewModel.EndID; inventoryID++)
{
Inventory newInventory = new Inventory
{
InventoryID = inventoryID,
ProductID = viewModel.InventoryBase.ProductID,
DateEdited = dateEdited,
EditedByUserID = WebSecurity.CurrentUserId
};
if(viewModel.InventoryBase.CustomProperties != null)
{
newInventory.CustomProperties = new List<CustomProperties>();
foreach(var customProperty in viewModel.InventoryBase.CustomProperties)
{
newInventory.CustomProperties.Add(customProperty);
}
}
Database.Inventories.Add(newInventory);
Database.SaveChanges();
}
Upvotes: 1