How can I add a new item to a EntitySet Using EF4? - c#

I tried to add some new items to entityset by creating new instance and add it using AddTo method then I called SaveChanges() method to update my database but no new recode had been added.
foreach (var newitem in newItemsList)
{
if (newitem.SomeValue > 0)
{
dbcontext.AddToMyEntityType(newitem);
}
}
dbcontext.SaveChanges();
but when I used MyEntityType.CreateMyEntityType() method all new items are saved into my database
foreach (var newitem in newItemsList)
{
if (newitem.SomeValue > 0)
{
MyEntityType _newEntity = MyEntityType.CreateMyEntityType();//I passed the required parameters
dbcontext.AddToMyEntityType(_newEntity);
}
}
dbcontext.SaveChanges();
why????
should I use Create method or there is another ways to do that?
Edit
I forget to mention that newitem have a navigation property(foreign key for a parent table) and I set this property with an a correct parent ID

There must be a difference between newItem and _newEntity on property level. CreateMyEntityType(...) doesn't do more then new MyEntityType and setting the properties you pass in. CreateMyEntityType(...) encourages to set properties for all required fields. Perhaps you set a required property (like a string) which isn't set in newItem. SaveChanges in your first example throws actually an exception because of the missing required field but you hid this exception (by try { ... } catch {} or something). Check in the debugger if SaveChanges passes without exception.
A hypothesis.

foreach (var newitem in newItemsList)
{
if (newitem.SomeValue > 0)
{
dbcontext.AddObject("entity set name", newitem);
}
}
dbcontext.SaveChanges();
or
var entitySet = dbcontext.CreateObjectSet<item type>();
foreach (var newitem in newItemsList)
{
if (newitem.SomeValue > 0)
{
entitySet.AddObject(newitem);
}
}
dbcontext.SaveChanges();

In first part you are not initializing the object of entity set
This will work if you initialize the object of entityset by doing some thing like this
foreach (var newitem in newItemsList)
{
if (newitem.SomeValue > 0)
{
MyEntityType obj = new MyEntityType
{
value1 = newitem.somevalue,
value2 = newitem.someothervalue
};
myContext.AddToMyEntityType(obj);
}
}
dbcontext.SaveChanges();
In your seceod part you have deifned the enititySet in which u wany add new object and also initilazes the object of the entiity by this
MyEntityType _newEntity = MyEntityType.CreateMyEntityType();
myContext.AddToMyEntityType(_newEntity);
Here you are telling that add _newEntity to my MyEntityType
AddToMyEntityType is a depreceated method for adding a new object to MyEntityType Entity Set..

Related

How to add new item into a list without overwriting the old item

I'm exporting some data from database to excel using CLOSEDXML. I need to add the corresponding objects/item to each object in the 'newModelist' IQueryable and add all the object to new List. In my case new row were added in the list using list.add method, however the old record is replaced by the next row/object. I'm not quite what would be the correct way to implement this.
var getData = _db.Database.Where(y => y.identifier == Identifier);
var newModelist = new MainModel();
var listXML= new List<listXML>();
foreach(var item in getData)
{
newModelist.col1 = item.A;
newModelist.col2 = item.B;
newModelist.col2 = item.C;
listXML.Add(newModelist);
}
You need to understand what an instance is.
You are currently modifying the same object instance. And you are adding the same instance to the List on every iteration.
Since List only stores the reference to an instance, your List currently contains multiple references to the same instance. Each index will return the same element.
If you want individual object instances you must create each using the new keyword:
foreach(var item in getData)
{
var newModelist = new MainModel
{
col1 = item.A,
col2 = item.B,
col3 = item.C
};
listXML.Add(newModelist);
}
MainModel is a reference type and modifying the value will reflect in the all the references, so you need to create a new instance while setting the properties in the loop. Moving creation of newModelList to for loop would do
foreach(var item in getData)
{
var newModelist = new MainModel();
newModelist.col1 = item.A;
newModelist.col2 = item.B;
newModelist.col2 = item.C;
listXML.Add(newModelist);
}

MVC List Error List<Model>

I'm using foreach to transfer data from list to another but when adding value updated automatically to last value added. For example:
list1 = [1,2,3]
list2 = new List<Model>()
foreach(var item in list1) {
list2.Add(item)
}
the result in list2 is [ 3, 3, 3]
Actually example is below :
var _sizes = new List<ProductsSize>();
var _size = new ProductsSize();
if (model.Dynamic_ProductsSize.Count > 0)
{
foreach (var item in model.Dynamic_ProductsSize)
{
_size.SizeId = item;
_sizes.Add(_size);
}
}
model.ProductsSize = _sizes.ToList();
I need to know why it only takes the last item and what is the solution for this case
You only have one ProductsSize object:
var _size = new ProductsSize();
And you keep modifying that same object. All references to that object, including any list elements it's been added to, get updated when you modify that one object.
Instead, create your new object in the loop:
foreach (var item in model.Dynamic_ProductsSize)
{
var _size = new ProductsSize();
_size.SizeId = item;
_sizes.Add(_size);
}
That way each element in the list is a new object instead of the same object added multiple times.
Side note, you have a few things in the code which aren't necessary. Checking the length before the loop, for example, as well as converting a list to a list at the end.
In fact, I imagine all of the code shown can be shortened to simply this:
model.ProductsSize = model.Dynamic_ProductsSize.Select(p => new ProductsSize { SizeId = p }).ToList();
In which case you're also just converting one model property to another model property. Why not put this logic in the model itself and skip the whole thing?
public IEnumerable<ProductsSize> ProductsSize
{
get { return this.Dynamic_ProductsSize.Select(p => new ProductsSize { SizeId = p });
}
Unless there's a particular reason you want the same data twice in two different properties that isn't clear from this code, having one set of data and just different views/calculations/etc. of that data is often preferred.
Create a new object before adding it to the list. You can use the object initializer syntax to keep it concise:
if (model.Dynamic_ProductsSize.Count > 0)
{
foreach (var item in model.Dynamic_ProductsSize)
{
_sizes.Add(new ProductsSize(){SizeId = item});
}
}

Updating an entity with a List

Controller
...
// field will represent a previously filled up field
Field field = this.unitOfWork.FieldRepository.GetByID( fieldID );
// But I want to remove some of these things called
// field attributes from its array, so I empty it out,
// and refill the list
field.FieldAttributes = null;
field.FieldAttributes = new List<FieldAttribute>();
foreach (var fieldAttributeGroup in fieldAttributes)
{
foreach (var fieldAttributeID in fieldAttributeGroup.Attributes)
{
if (fieldAttributeID != "false" && fieldAttributeID != null)
{
// dbFieldAttribute is from the database
FieldAttribute dbFieldAttribute = this.unitOfWork.FieldAttributeRepository.GetByID(Convert.ToInt32(fieldAttributeID));
// I fill the new field up
field.FieldAttributes.Add(dbFieldAttribute);
}
}
}
// I send the field to the repository:
this.unitOfWork.FieldRepository.Update( field );
Repository
public void Update( Field field )
{
Field dbEntity = context.Fields.Find( field.FieldID );
dbEntity.FieldAttributes = field.FieldAttributes;
context.SaveChanges();
The problem:
Existing field attribute relationships that were attached to a field in the database remain attached even though I have set that attribute equal to the new set of field attributes.
The question:
Do I have to remove entries that existed... explicitly or is there a way to make Entity framework handle all of the relationship modifications.. obviously some existing field attribute relationships are not explicitly remove at this point.

Use the foreach for properties of class

I'm writing an function to update a row in table (SQLite). At one time I only need to update certain columns of that row.
My Video class (and table) has these properties (and columns):
Id, Name, Lyric, Cover,Gendre, Url. ( they're all string)
Now, for example, I need to update the lyric and cover of 1 row in table , I'm using this code:
string id = // still keep the old id, this's the PK of table;
string lyric = //get new lyric;
string cover = // get new cover;
Video item = new Video(){Id = id, Lyric = lyric, Cover = cover};
SQLiteAccess.EditVideoInfo(item);
Here's the EditVideoInfo
public static void EditVideoInfo(Video item)
{
var conn = new SQLiteConnection(mypath);
using (conn)
{
var list = conn.Query<Video>("SELECT * FROM Video WHERE Id =?", item.Id);
if (list.Count >0)
{
var editItem = list.First(); // -> Get the item need to updated
/// Here's where I'm stuck
conn.Update(editItem);
}
}
}
So how can I read "foreach" each property of the new item and update to the old item's property if that property isn't null ?
Something like below.
var props = typeof(Video).GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.GetProperty|BindingFlags.SetProperty);
foreach (var prop in props) {
var propVal = prop.GetValue(item, null);
if (propVal != null)
prop.SetValue(editItem, propVal, null);
}
You can use reflection to get all the properties of the Video item (take a look at http://msdn.microsoft.com/en-us/library/kyaxdd3x(v=vs.110).aspx) but the solution would be slow and messy. Just write the test and update code for each property.
My first approach to do this is to create a dictionary
Dictionary<string, string> _properties = new Dictionary<string, string>();
_properties["id"] = "myID"
_properties["lyric"] = "some other string"
and then you can iterate through it with a foreach
foreach (var prop in _properties)
{
// do something with prop
}

Deleting and Adding child entities in same transaction confusing nhibernate

I'm getting the classic error:
'deleted object would be re-saved by cascade
(remove deleted object from associations)[DrillingContracts.Domain.TrackedField#3216'
But with an added twist, The error is originating entirely because I'm deleting one entity and adding a NEW one.
I empty all the pre-existing children with this method
public void RemoveChildren(TrackedNode parentNode)
{
foreach (TrackedField trackedField in parentNode.ChildNodes)
{
_trackedFieldRepository.Delete(trackedField);
parentNode.RemoveChildNode(trackedField);
}
}
Then add the new ones immediately next
public virtual void AddTrackedChildFieldsToTrackedCell(
params TrackedField[] nodes)
{
foreach (var field in nodes)
{
if (IsPath(field.Name))
{
throw new InvalidTrackedFieldNameException(
"The value " + field.Name + " is not a valid tracked field name.");
}
field.Supplement = this;
_trackedFields.Add(field);
}
}
For those of you who want to know what is happening in the repository the best answer I have is magic. 10,000% magic. The original developer used NCommon. Both of these methods are called from a method wrapped in the NCommon.UnitOfWork attribute.
It should be noted that each method performs as expected on its own. (IE, no fields to delete the add works, and likewise, no fields to add the delete works.)
EDIT
[HttpPost]
[UnitOfWork(Scope = FilterScope.Result)]
public ActionResult SaveEditMode(long id, AddTrackedRowViewModel model, string editMode, List<string> elementNames, string provisionData)
{
var supplement = _supplementCoordinator.GetSupplement(id);
var table = supplement.TrackedTables.First(x => x.Name == model.Name);
var valueAttributes = JsonSerializer.DeserializeFromString<List<ValueAttributeViewModel>>(provisionData);
foreach (var prop in valueAttributes)
{
supplement.Set(prop.Attribute, prop.Value, false);
}
var cell = table.TrackedRows.First(x => x.Ordinal == model.Ordinal).TrackedCells.First(x => x.Name == "Detail");
_supplementCoordinator.RemoveChildren(cell);
if (elementNames != null)
{
var childNodes = elementNames.Select((t, i) => new TrackedField(cell, t, i)).ToList();
supplement.AddTrackedChildFieldsToTrackedCell(childNodes.ToArray());
}
return SwitchEditMode(model, editMode, table);
}
Answer
public void AddChildren(Supplement supplement, TrackedNode parentNode, params TrackedField[] nodes)
{
foreach (TrackedField trackedField in nodes)
{
parentNode.AddChildNode(trackedField);
}
supplement.AddTrackedChildFieldsToTrackedCell();
}
I wasn't getting them added as new entitles to the parent node, just the associated supplement.
Just for completeness. The message 'deleted object would be re-saved..' was caused by the explicit call session.Delete(instance).
In this case, we only need to 1) remove such item from the old parent collection and 2) append it to new parent. The cascade mapping and session.Flush() will properly upate DB.
Final note: such a "movement" must be done inside one session/transaction, to avoid other issues (e.g 'Row was updated or deleted by another transaction...').

Categories

Resources