There is an update method throws exception but it works fine in first loging after second attempt throws exception with message;
**
Additional information: Attaching an entity of type
'Hsys.InfluenzaTaniBilgisi' failed because another entity of the same
type already has the same primary key value. This can happen when
using the 'Attach' method or setting the state of an entity to
'Unchanged' or 'Modified' if any entities in the graph have
conflicting key values. This may be because some entities are new and
have not yet received database-generated key values. In this case use
the 'Add' method or the 'Added' entity state to track the graph and
then set the state of non-new entities to 'Unchanged' or 'Modified' as
appropriate.
**
Iknow its common and found many smilar issue but I couldnt make it work..
here is code piece;
public void CreateUpdateInfluenzaTani(InfluenzaTaniBilgisi taniBilgisi)
{
using (HsysDbContext con = new HsysDbContext())
{
if (con.InfluenzaTestTanilari.Any(x => x.ICD10TaniKodu == taniBilgisi.ICD10Kodu && x.IsDeleted != true))
{
var taniExist = con.InfluenzaTaniBilgisi.FirstOrDefault(x => x.MuayeneId == taniBilgisi.MuayeneId && x.ICD10K
odu == taniBilgisi.ICD10Kodu && x.IsDeleted != true);
if (taniExist == null)
{
taniBilgisi.ObjectState = Framework.Entities.ObjectState.Added;
Create(taniBilgisi);
}
else
{
taniExist.HastaYasi = taniBilgisi.HastaYasi;
taniExist.HekimTC = taniBilgisi.HekimTC;
taniExist.ObjectState = Framework.Entities.ObjectState.Modified;
Update(taniExist);// throws Exception!
}
}
}
}
taniExist.ObjectState = Framework.Entities.ObjectState.Modified;
This is your issue.
You cannot use the Framework.Entities.ObjectState.Modified; on an existing key, entity frame work won't allow that.
You need to first do this:
taniExist.ObjectState = Framework.Entities.ObjectState.Added;
and then:
taniExist.ObjectState = Framework.Entities.ObjectState.Modified;
Your code will look like this:
taniExist.HastaYasi = taniBilgisi.HastaYasi;
taniExist.HekimTC = taniBilgisi.HekimTC;
taniExist.ObjectState = Framework.Entities.ObjectState.Added;
Update(taniExist);
Framework.Entities.ObjectState.Modified;
Related
The method that i used to delete an item from database is throwing back the error
"The object cannot be deleted because it was not found in the ObjectStateManager."
I followed multiple suggestions online to try to attach it but it was throwing back another error
"Attaching an entity of type 'databaseName' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate."
public bool deleteItem(Item s)
{
bool success = false;
using (DBEntities cxt = new DBEntities())
{
var saving = (from i in cxt.Items
where i.Id == s.Id
select i).FirstOrDefault();
cxt.Entry(s).State = System.Data.Entity.EntityState.Deleted;
//cxt.Items.Attach(s);
cxt.Items.Remove(s);
int delete = cxt.SaveChanges();
if (delete == 1)
{
success = true;
}
return success;
}
}
You can do this with one database call instead of 2. Attach the entity and then call Remove on the DbSet to delete it.
public bool deleteItem(Item s)
{
bool success = false;
using (DBEntities cxt = new DecagonDBEntities())
{
cxt.Items.Attach(s);
cxt.Items.Remove(s);
int delete = cxt.SaveChanges();
bool success = delete == 1;
return success;
}
}
If you still want to retrieve it for validation
public bool deleteItem(Item s)
{
bool success = false;
using (DBEntities cxt = new DecagonDBEntities())
{
var itemToDelete = cxt.Items.SingleOrDefault(_ => _.Id == s.Id);
// validate itemToDelete like check for null etc
cxt.Items.Remove(itemToDelete);
int delete = cxt.SaveChanges();
bool success = delete == 1;
return success;
}
}
I am struggling to implement a very basic "InsertOrUpdate()" method on a DbContext. I tried following the advice in this post.
private static bool SaveItem<TEntity>(Object objToSave, TEntity existing = null) where TEntity : class
{
try
{
/////////////////////////////////////////
// BLOCK A
if(existing != null)
db.Set<TEntity>().Attach(existing);
/////////////////////////////////////////
db.Entry(objToSave).State = existing!=null ? EntityState.Modified : EntityState.Added;
db.SaveChanges();
} catch(Exception e)
{
Logger.Exception(e);
return false;
}
return true;
}
An example call to is the following:
SaveItem(item, db.MyInstances.Where(dbItem => dbItem.ID == item.ID).FirstOrDefault());
Some definitions:
class MyInstancesDbContext: DbContext { ... }
private static MyInstancesDbContext db = new MyInstancesDbContext();
As I understand it, in that call the .Where() will cause an attachment of some sort. So I've tried both including the small block of code labeled "A" and removing it. Both of which give me the same kind of error:
System.InvalidOperationException: Attaching an entity of type '...MyInstance' failed because a
nother entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any en
tities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the '
Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
I found this popular related answer to this error where the user suggests using AsNoTracking(), but that instead makes me feel like I don't fundamentally understand something or am trying to ignore some error.
I'd greatly appreciate any advice.
I think what you're missing is that the DbContext tracks entities, and it doesn't like tracking entities of the same type with the same primary key.
When you call this:
db.MyInstances.Where(dbItem => dbItem.ID == item.ID).FirstOrDefault()
you've loaded an entity of MyInstance with primary key == item.ID into the context if it exists in the database.
This line is completely unneeded because existing would already be attached -- but that probably doesn't cause the error.
if(existing != null)
db.Set<TEntity>().Attach(existing);
The problem is probably here:
db.Entry(objToSave).State =
existing != null ? EntityState.Modified : EntityState.Added;
If existing == null, you might be okay, because this line will attach objToSave, but if existing exists, you'll have a problem because you'll be trying to attach objToSave which has the same type and primary key as existing.
Instead, you could try using objToSave to set the values for the attached entity:
db.Entry(existing).CurrentValues.SetValues(objToSave);
So objToSave will not be attached if there is an existing record.
https://msdn.microsoft.com/en-us/data/jj592677.aspx
Error message: Attaching an entity of type failed because another entity of the same type already has the same primary key value.
Question: How do I attached an entity in a similar fashion as demonstrated in the AttachActivity method in the code below?
I have to assume the "another entity" part of the error message above refers to an object that exists in memory but is out of scope (??). I note this because the Local property of the DBSet for the entity type I am trying to attach returns zero.
I am reasonably confident the entities do not exist in the context because I step through the code and watch the context as it is created. The entities are added in the few lines immediately following creation of the dbcontext.
Am testing for attached entities as specified here:what is the most reasonable way to find out if entity is attached to dbContext or not?
When looking at locals in the locals window of visual studio I see no entities of type Activity (regardless of ID) except the one I am trying to attach.
The code executes in this order: Try -> ModifyProject -> AttachActivity
Code fails in the AttachActivity at the commented line.
Note the code between the debug comments which will throw if any entities have been added to the context.
private string AttachActivity(Activity activity)
{
string errorMsg = ValidateActivity(activity); // has no code yet. No. It does not query db.
if(String.IsNullOrEmpty(errorMsg))
{
// debug
var state = db.Entry(activity).State; // Detached
int activityCount = db.Activities.Local.Count;
int projectCount = db.Activities.Local.Count;
if (activityCount > 0 || projectCount > 0)
throw new Exception("objects exist in dbcontext");
// end debug
if (activity.ID == 0)
db.Activities.Add(activity);
else
{
db.Activities.Attach(activity); // throws here
db.Entry(activity).State = System.Data.Entity.EntityState.Modified;
}
}
return errorMsg;
}
public int ModifyProject(Presentation.PresProject presProject, out int id, out string errorMsg)
{
// snip
foreach (PresActivity presActivity in presProject.Activities)
{
Activity a = presActivity.ToActivity(); // returns new Activity object
errorMsg = ValidateActivity(a); // has no code yet. No. It does not query db.
if (String.IsNullOrEmpty(errorMsg))
{
a.Project = project;
project.Activities.Add(a);
AttachActivity(a);
}
else
break;
}
if (string.IsNullOrEmpty(errorMsg))
{
if (project.ID == 0)
db.Projects.Add(project);
else
db.AttachAsModfied(project);
saveCount = db.SaveChanges();
id = project.ID;
}
return saveCount;
}
This is the class that news up the dbContext:
public void Try(Action<IServices> work)
{
using(IServices client = GetClient()) // dbContext is newd up here
{
try
{
work(client); // ModifyProject is called here
HangUp(client, false);
}
catch (CommunicationException e)
{
HangUp(client, true);
}
catch (TimeoutException e)
{
HangUp(client, true);
}
catch (Exception e)
{
HangUp(client, true);
throw;
}
}
I am not asking: How do I use AsNoTracking What difference does .AsNoTracking() make?
One solution to avoid receiving this error is using Find method. before attaching entity, query DbContext for desired entity, if entity exists in memory you get local entity otherwise entity will be retrieved from database.
private void AttachActivity(Activity activity)
{
var activityInDb = db.Activities.Find(activity.Id);
// Activity does not exist in database and it's new one
if(activityInDb == null)
{
db.Activities.Add(activity);
return;
}
// Activity already exist in database and modify it
db.Entry(activityInDb).CurrentValues.SetValues(activity);
db.Entry(activityInDb ).State = EntityState.Modified;
}
Attaching an entity of type failed because another entity of the same type already has the same primary key value. This can happen when using the Attach method or setting the state of an entity to Unchanged or Modified if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the Add.
The solution is that
if you had to use GetAll()
public virtual IEnumerable<T> GetAll()
{
return dbSet.ToList();
}
Change To
public virtual IEnumerable<T> GetAll()
{
return dbSet.AsNoTracking().ToList();
}
I resolved this error by changing Update method like below.
if you are using generic repository and Entity
_dbContext.Set<T>().AddOrUpdate(entityToBeUpdatedWithId);
or normal(non-generic) repository and entity , then
_dbContext.Set<TaskEntity>().AddOrUpdate(entityToBeUpdatedWithId);
If you use AddOrUpdate() method, please make sure you have added
System.Data.Entity.Migrations namespace.
I have a problem with entity framework code first six working so disconnected. The problem occurs when I want to mark an entity as modified, the entity has association properties loaded with a new instance of DbContext, to be more precise the source of my hit and then get the save.
public List<Venta> Get(Expression<Func<Venta, bool>> predicate)
{
try
{
int num = 0;
List<Venta> ventas = new List<Venta>();
using (_context = new MyContext(MyContext.GetConnectionString()))
{
if (predicate == null)
ventas = _context.Ventas.Include("Mesa").Include("Usuario").Include("Pago").ToList();
else
ventas = _context.Ventas.Include("Mesa").Include("Usuario").Include("Pago").Where(predicate).ToList();
}
//I use the other repo to load related entities
UsuarioRepository userRepo = new UsuarioRepository();
foreach (Venta item in ventas)
{
item.GetType().GetProperty("Usuario").SetValue(item, userRepo.Get(u => u.Id == item.UsuarioId).First(), null);
}
//I use the other repo to load related entities
ProductoRepository prodRepo = new ProductoRepository();
foreach (VentaProducto item in ventas.SelectMany(vta => vta.Detalle).ToList())
{
Producto p = prodRepo.Get(prod => item.ProductoId == prod.Id).First();
item.GetType().GetProperty("Producto").SetValue(item, p, null);
}
ventas.ForEach(vta => vta.State = DomainEntityState.Unchanged);
return ventas;
}
catch (Exception ex)
{
throw new Exception("Error al traer las Ventas", ex);
}
}
public override int Save(Venta venta)
{
int saves = 0;
EntityState state;
EntityState stateProducto;
//New Instance of the context without entities in the DbSet's
using (MyContext context = new MyContext(MyContext.GetConnectionString()))
{
try
{
if (venta.IsNewEntity) //Venta nueva
{
state = EntityState.Added;
stateProducto = EntityState.Modified;
}
else
{
state = EntityState.Modified;
stateProducto = EntityState.Modified;
}
//int usuarios = context.Usuarios.Local.Count; //I get 0
//int productos = context.Productos.Local.Count; //I get 0
//int ventasProductos = context.VentasProducto.Local.Count; // I get 0
venta.Usuario = null;
if (venta.Pago != null)
venta.Pago.Usuario = null;
if (venta.Pago != null)
{
EntityState estadoPago = context.GetEntityState(venta.Pago);
}
//HERE IS THE PROBLEM
context.SetEntityState(venta, state);
saves = context.SaveChanges();
}
catch (Exception ex)
{
throw new Exception("Error al grabar la venta", ex);
}
}
return saves;
}
Finally I get the following error ....
Attaching an entity of type 'Jackie.Domain.Entities.Usuario' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
The most strange is that if I load all entities with the same instance of context does not have that problem. It will be a bug? No longer think of anything more. Thank you all. Made with google translator.
There are (at least) two Usuario properties in the object graph - venta.Usuario and venta.Pago.Usuario. By attaching the venta entity, the entity objects in these two Usuario properties will be attached as Unmodified. If these two properties hold two different instances of the Usuario class with the same PK value, when the second is attached it will throw the error you received. This seems quite possible as you're loading navigation properties via different instances of the context with some eager loading thrown into the mix.
Break at the call to context.SetEntityState(venta, state) and see if those two Usuario objects are actually the same instance or two different instances with the same PK value(s).
I use repository with Update method. In this method I need to check some conditions, finding updating entity in DB before actual update. I use one context for both - Find and Update operations inside one transaction. But when I try to update entity I get an exception:
"Attaching an entity of type 'MyNamespace.MyEntityType' failed because another entity of the same type already has the same primary key value"
public void Update(SomeType entity)
{
using (var context = new MyEntities())
{
using (var transaction = context.Database.BeginTransaction(IsolationLevel.RepeatableRead))
{
try
{
// check conditions
var root = context.MyEntitySet
.Where(e => e.Parent == null); // entity.Parent == null
if(root ...)
; // return
// HERE I got an error described above
context.Entry(entity).State = EntityState.Modified;
context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
}
I need to load entity with same Id from DB first, check some conditions and if ok, update entity. But after "Get" entity attaches to ChangeTracker with "Detached" state and when I try to change state to "Modified" I got an error.
I've already tried:
if (IsAttached(entity, out attachedEntity))
context.Entry(attachedEntity).CurrentValues.SetValues(entity);
but my original entity object stays unchanged with DB generated values. State = EntityState.Modified works as I need, but how can I remove preloaded entity from ChangeTracker?