EF add child to existing parent throws DbUpdateConcurrencyException - c#

Using EF 6.0, I have the following code in my app
using (var db = new TrackingEntities())
{
foreach (var p in points)
{
var parent= db.Parents.Find(points[0].Imei);
var record = new Child()
{
.....
};
parent.Children.Add(record);
db.SaveChanges();
}
}
and it throws
Additional information: Store update, insert, or delete statement
affected an unexpected number of rows (0). Entities may have been
modified or deleted since entities were loaded. Refresh
ObjectStateManager entries.
Update:
Something weird is happening. When I test the code while in started it to debug, it works fine and add children to parent. But when I disconnected it from debug and run the code again, it throws the mentioned error.
Here is the models:
public partial class Child
{
public long Id { get; set; }
public string ParentPK { get; set; }
public virtual TB_Parent TB_Parent { get; set; }
}
public partial class TB_Parent
{
public long ParentID { get; set; }
public virtual ICollection<Child> Children { get; set; }
public TB_Parent()
{
this.Children = new HashSet<Child>();
}
}

You need to add the Child to the appropriate DB Set prior to saving.
Try db.Childs.Add(record); or the equivalent depending on how you've named things.

Related

Database operation expected to affect 1 row(s) but actually affected 50(db sequence next number) row(s)

I use entity framework 2.2.6. I have AddOrUpdate method. When client try to operate(insert or update) on entity I check if entity exist on db by unique values and I set old data id value to new data id value and I set it as updated. If not exist I set it as insert
public void AddOrUpdate(TEntity entity, Expression<Func<TEntity, bool>> predicate)
{
var oldEntity = Get(predicate);
DetachEntry(oldEntity);
if (oldEntity != null)
{
var idProperty = entity.GetType().GetProperties().First(x => x.Name == "Id");
idProperty.SetValue(entity, idProperty.GetValue(oldEntity, null));
Update(entity);
}
else
Add(entity);
}
When I try simple entity It works fine. But when I use very complex type I get following exception.
Database operation expected to affect 1 row(s) but actually affected
50 row(s). Data may have been modified or deleted since entities were
loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for
information on understanding and handling optimistic concurrency
exceptions.
My complex type is like this.
public class FamilyMemberInfo
{
public int Id { get; set; }
public int AppealId { get; set; }
public int MemberId { get; set; }
public FamilyMember FamilyMember { get; set; }
public Appeal Appeal { get; set; }
public ICollection<FamilyMemberContact> Contacts { get; set; }
public ICollection<FamilyMemberCrime> Crimes { get; set; }
public ICollection<FamilyMemberDisease> Diseases { get; set; }
public ICollection<FamilyMemberPaymentLiability> PaymentLiabilities { get; set; }
}
After call AddOrUpdate method I look ChangeTraker every thing seem ok. And it generated very good query.
I can not find exception reason. I see familar errors on stakoverflow. But every solitions not work for me.
Edit
When I comment two child entities(it is not important which ones) everythink works fine

EF is trying to insert new child record before new parent record during SaveChanges

I am using database first and have a parent entity that has a collection of child entities. When I am adding both at the same time I am getting a FK constraint in the DB and when I log EF's commands I see that it is sending the sql command to insert the child record first in the UOW and of course it blows up.
The code is first adding the Ticket using dbSet.Add and then it adds the StockTicket to Ticket.StockTickets. It then calls SaveChanges()
I have also tried to add both Ticket and StockTicket to their respective dbSets and then manually add the StockTicket to Ticket.StockTickets and the Ticket to StockTicket.Ticket, but that doesn't work either
Nothing works and I haven't run into this before; I have worked with EF quite a bit.
public partial class Ticket
{
public Ticket()
{
this.StockTickets = new HashSet<StockTicket>();
}
public long TicketID { get; set; }
...
public virtual ICollection<StockTicket> StockTickets { get; set; }
}
public partial class StockTicket
{
public long StockTicketID { get; set; }
...
public virtual Ticket Ticket { get; set; }
}
// base repository methods
protected void Insert(TEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity", "The entity argument is null.");
}
var entry = _context.Entry(entity);
entry.Property("isActive").CurrentValue = true;
_dbSet.Add(entity);
}
public void Save()
{
_context.SaveChanges();
}
Calling code in my service:
ticket.ticketID = GetNextSequence();
_repository.Insert(ticket);
ticket.StockTickets.Add(stockTicket);
_repository.Save();

Converting a string into a List and then using Entity Framework to insert into Database

I am converting a string into a list and then trying to use entity framework to insert it into a DB. The issue that I am having is that I don't know how to save the changes to the DB.
This is the code that I am trying to use and is where the string is converted to a list:
if (intCounter == 0)
{
return JsonConvert.DeserializeObject<List<foo>>(jsonString).Cast<T>().ToList();
}
Then in a seperate class below.
ConvertJson.Convert<CouncilEvent>(strResponseJSONContent, intCounter);
The Entity Framework Model that I am trying to use for the list.
namespace foo.Models
{
public partial class foo
{
public foo()
{
this.EventDates = new List<EventDate>();
}
public System.Guid foo_PK { get; set; }
public string EntityID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public bool Adult { get; set; }
}
}
The class foo contains properties that match those in the string.
It is this foo that I am then trying to insert into the DB. foo is also part of my Entity Framework model.
I have never used a list in this situation before and I thought it would just be a matter of using db.SaveChanges() but that doesn't seem to work. Where would I place the necessary lines of code such as using (db = new contextFoo) and db.SaveChanges(). Also do I need to add the items? I haven't because I thought I was already adding them to the class and therefore didn't need to do this manually?
db.SaveChanges() will only 'update' your database to what was changed. So, you need to add something to the database, and then call SaveChanges() for it to work.
You can loop the list to add the objects to the context, then call SaveChanges()...
var councilEvents = ConvertJson.Convert<CouncilEvent>(strResponseJSONContent, intCounter);
using (var db = new contextFoo())
{
foreach (var councilEvent in councilEvents)
{
db.CouncilEvents.Add(councilEvent);
}
db.SaveChanges();
}

Many to Many relationship Entity Framework creating new rows

I'm building a feedback functionality. The feedback is supposed to have multiple categories and it should be possible to find feedback based on a category so there is a many to many relationship.
I've set up the following code for this, its designed as code first.
The feeback item:
public class FeedbackItem
{
public FeedbackItem()
{
}
[Key]
public long Id { get; set; }
public virtual ICollection<FeedbackCategory> Categorys { get; set; }
//public
public string Content { get; set; }
public bool Notify { get; set; }
public string SubscriptionUserName { get; set; }
public string SubscriptionUserEmail { get; set; }
public long SubscriptionId { get; set; }
}
The feedback category:
public class FeedbackCategory
{
[Key]
public int Id { get; set; }
public string Value { get; set; }
public virtual ICollection<FeedbackItem> Feedbacks { get; set; }
}
The Database Context:
public class FeedbackContext : DbContext, IFeedbackContext
{
public FeedbackContext() : base("DefaultConnection")
{
//Database.SetInitializer<FeedbackContext>(new FeedbackContextDbInitializer());
}
public DbSet<FeedbackItem> FeedbackItems { get; set; }
public DbSet<FeedbackCategory> Categories { get; set; }
}
And the Initializer
class FeedbackContextDbInitializer : DropCreateDatabaseAlways<FeedbackContext>
{
protected override void Seed(FeedbackContext context)
{
IList<FeedbackCategory> categories = new List<FeedbackCategory>()
{
new FeedbackCategory() { Value = "Android" },
new FeedbackCategory() { Value = "API" }
};
foreach (var feedbackCategory in categories)
{
context.Categories.Add(feedbackCategory);
}
base.Seed(context);
}
}
The code above generates three tables when ran. These being FeedbackCategories, FeedbackCategoryFeedbackItems and FeedbackItems
The table FeedbackCategories is seeded with some already existing categories. The trouble comes when I try to create a new FeedbackItem that has one or more categories.
The Json i provide is the following:
{
"categorys": [
{
"$id": "1",
"Feedbacks": [],
"Id": 1,
"Value": "Android"
}
],
"subscriptionUserName": "name",
"subscriptionUserEmail": "my#email.com",
"content": "this is a feedback item",
"notify": false,
"subscriptionId": 2
}
This is converted into a FeedbackItem and handled by the following code
public class FeedbackSqlRepository : IFeedbackSqlRepository
{
public int Create(FeedbackItem feedback)
{
if (feedback == null)
{
throw new ArgumentNullException("feedback", "FeedbackItem cannot be empty.");
}
using (var context = new FeedbackContext())
{
context.FeedbackItems.Add(feedback);
return context.SaveChanges();
}
}
}
The thing that happens here is that EF creates a new FeedbackItem, a new FeedbackCategory an maps the created feedback item to the newly created feedback category in the FeedbackCategoryFeedbackItems table.
this is not the working i want
I want the following:
Create a new FeedbackItem and reverence an existing FeedbackCategory in the FeedbackCategoryFeedbackItems table. My knowledge of EF is too little to understand what's going wrong here and what to do to get the preferred working.
========
Fixed the issue with the following code inside the Create method from the FeedbackSqlRepository:
foreach (FeedbackCategory feedbackCategory in feedback.Categories)
{
context.Entry(feedbackCategory).State = EntityState.Unchanged;
}
context.FeedbackItems.Add(feedback);
return context.SaveChanges();
Entity Framework will not examine entity contents and determine for you if they are new or added.
DbSet.Add() causes ALL entities in an object graph to be marked as added and to generate inserts when you call SaveChanges().
DbSet.Attach() leaves all entities marked as Unmodified.
If some of your entities are new, some are modified and some are just references then you should use either Add() or Attach() and then manually set entity states where necessary before calling SaveChanges().
DbContext.Entry(entity).State = EntityState.Unmodified

MVC3 EF4 duplicates foreign key object on save

I'm using MVC3 with EF4 code-first. I have the following model:
public class Order {
public int ID { get; set; }
[Required]
public float Price { get; set; }
[Required]
public int PayMethodId { get; set; }
public PayMethod PayMethod { get; set; }
public int? SpecificEventId { get; set; }
public SpecificEvent SpecificEvent { get; set; }
public int? SeasonalTicketId { get; set; }
public SeasonalTicket SeasonalTicket { get; set; }
}
When I try to save an Order object with specificEventId = 2 and specificEvent = X, a new SpecificEvent object is created in the DB, even though there's already a specific event X with ID 2 in the DB. When i try with specificEventId = 2 and specificEvent = null I get a data validation error.
What am I doing wrong? I want SpecificEvent and SeasonalTicket to be nullable, and I don't want EF4 to create a new instance of these objects in the DB whenever I save 'Order'.
Update
This is my code for saving Order in the DB:
public void SaveOrder(Order order)
{
Order fromDb = null;
// If editing an existing object.
if ((fromDb = GetOrder(order.ID)) != null)
{
db = new TicketsDbContext();
db.Entry(order).State = System.Data.EntityState.Modified;
db.SaveChanges();
}
// If adding a new object.
else
{
db.orders.Add(order);
db.SaveChanges();
}
}
When I save, I do reach the else clause.
The real question is, where did you get the instance of X from? It appears as though EF has no knowledge of this instance. You either need to fetch the already existing SpecificEvent through EF and use the proxy it returns to set your navigation property, or else tell EF to "attach" X, so that it knows what your intent is. As far as EF knows, it appears, you are trying to send it a new instance with a conflicting Id, so it is properly issuing the error.

Categories