Found the issue...I had MergeOption.NoTracking set on my context.entity...sigh
Not sure what I'm doing wrong.
The object cannot be deleted because it was not found in the ObjectStateManager.
var deleteOrders = db.TABLE.Where(x => x.WCCR_ID == WccrId && x.ADAM == null).ToList();
foreach (var item in deleteOrders)
{
db.TABLE.DeleteObject(item);
}
db.SaveChanges();
I tried attaching the item db.Attach(item), but that throws an error 'Object with the same Key already exists'.
thanks for your help. cheers
Your code looks good. Try using:
var deleteOrders = db.TABLE.Where(x => x.WCCR_ID == WccrId && x.ADAM == null)
.ToList();
foreach (var item in deleteOrders)
{
db.Entry(item).State = System.Data.EntityState.Deleted;
}
db.SaveChanges();
UPDATE
EF 4.0 uses the ObjectContext class.
using(YourContext ctx = new YourContext())
{
ctx.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Deleted);
}
EF 4.1 uses the DbContext class in which the methods like Set<T> and Entry are defined.
using(YourContext ctx = new YourContext())
{
ctx.Entry(entity).State = System.Data.EntityState.Deleted;
}
UPDATE 2
The NuGet package only includes the EF 4.1 runtime and does not include the Visual Studio item templates for using DbContext with Model First and Database First development.
Download: http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=26825
Related
I want to find any entity that inherits from DbEntity and has the field DeletedDate set to a value older than 100 days.
I have managed to piece together this code. But I am unsure of how I can go from this to querying the database for relevant entities.
var softDeletableEntities = _applicationContext.Model.GetEntityTypes()
.Where(e =>
typeof(DbEntity).IsAssignableFrom(e.ClrType)
&& e.BaseType == null
);
foreach (var entity in softDeletableEntities)
{
var entry = _applicationContext.Entry(entity.ClrType);
entry.Property<DateTimeOffset?>("DeletedDate");
// how do I find any Entity where (DeletedDate != null) and delete it?
}
I was hoping to be able to do something like this, but Set<> can't be used like that:
// Not ok to use Set<>() as below. Gives: 'entity' is a variable but is used like a type
var dataSet = _applicationContext.Set<entity.ClrType>();
var deleteOlderThan = DateTime.Now.AddDays(-100);
var toDelete = dataSet.Where(x => x.DeletedDate < deleteOlderThan);
dataSet.RemoveRange(toDelete);
_applicationContext.SaveChanges();
Any tips :)?
I would suggest to use EF Core extension linq2db.EntityFrameworkCore, note that I'm one of the creators. Install appropriate version 5.x for EF Core 5, 6.x for EF Core 6, etc.
Then you can execute the following query:
var dataSet = _applicationContext.Set<entity.ClrType>();
var deleteOlderThan = DateTime.Now.AddDays(-100);
var toDelete = dataSet.Where(x => x.DeletedDate < deleteOlderThan);
toDelete.Delete(); // method from Extension
I have searched and find 2 way to update object in EF
var attachedEntity = _context.EntityClasses.Local.First(t => t.Id == entity.Id);
//We have it in the context, need to update.
if (attachedEntity != null)
{
var attachedEntry = _context.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(entity);
}
else
{
////If it's not found locally, we can attach it by setting state to modified.
////This would result in a SQL update statement for all fields
////when SaveChanges is called.
var entry = _context.Entry(entity);
entry.State = EntityState.Modified;
}
_context.SaveChanges();
And other way is seem more easy
var entity = _context.EntityClasses.FirstOrDefault(t => t.Id == entity.Id);
_context.Entry(entity ).EntityState.Modified
_context.SaveChanges();
What is best way to update object?
NOTE: the performence is importance with me
_context.EntityClasses.Local.First(t => t.Id == entity.Id)
=> means that you want to double check the entity on local (the latest loading from DB) and it is not send to DB to find the record so the performance is faster.
_context.EntityClasses.FirstOrDefault(t => t.Id == entity.Id): This command is look up the entity in DB. That means EF creates the query and look up in DB.
The below link is the difference of between Entity.Local.Find & Entity.Find http://msdn.microsoft.com/en-us/data/jj592872.aspx
Hope it helps!
I am having an issue understanding why when adding a new entity to a DbSet of ObjectContext, that entity is not found will looking it up again.
using (var db = new SmartrailDB())
{
var cart01 = db.Carts.SingleOrDefault(x => x.Number == 0);
if (cart01 == null)
{
cart01 = new Cart { Number = 0 };
db.Carts.Add(cart01);
}
var cart02 = db.Carts.SingleOrDefault(x => x.Number == 0); // Should find the cart I just added - right?
Assert.IsNotNull(cart02); // Fails because cart02 does not exist in the db.Carts collection
}
Is anyone able to tell me what I am doing wrong here?
Also late on a Friday here so brain half asleep now.
You have to update your context before you try to access the entity. Just do:
db.SaveChanges(); right after db.Cart.Add(cart01);
I have an ASP.NET WebForms project with N-Layers using Entity Framework 5.
I have two entities: Cliente and Banda.
One Cliente may have many Banda's, and one Banda may have many Cliente's
In the bussines layer I have this code:
public void Update(Cliente cliente)
{
using (MegaStudioEntities contexto = new MegaStudioEntities())
{
if (contexto.Entry(cliente).State == EntityState.Detached)
contexto.Entry(cliente).State = EntityState.Modified;
//Delete existing relations
var qBandas = from qb in contexto.Bandas.Where(b => b.Clientes.Any(c => c.IdCliente == cliente.IdCliente))
select qb;
foreach (Banda b in qBandas.ToList())
((IObjectContextAdapter)contexto).ObjectContext.ObjectStateManager.ChangeRelationshipState(cliente, b, c => c.Bandas, EntityState.Deleted);
contexto.SaveChanges();
//Adding new relations
foreach (Banda banda in cliente.Bandas)
{
contexto.Bandas.Attach(banda);
((IObjectContextAdapter)contexto).ObjectContext.ObjectStateManager.ChangeRelationshipState(cliente, banda, c => c.Bandas, EntityState.Added);
}
cliente.TipoCliente = contexto.TipoClientes.Find(cliente.IdTipoCliente);
cliente.FechaModificacion = System.DateTime.Now;
Encriptar(cliente);
contexto.SaveChanges();
}
}
The first time I call Update method, run sucessfully, but the second time I get this error:
"An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key."
What I forget to close?
This is the correct way to update many to many relations in EF5?
Thanks in advance!!!
Martin
UPDATE 1:
Finally my code is like that:
public void Update(Cliente cliente)
{
using (MegaStudioEntities contexto = new MegaStudioEntities())
{
Cliente savedClient = contexto.Clientes.Find(cliente.IdCliente);
foreach (var banda in savedClient.Bandas.ToList())
{
savedClient.Bandas.Remove(contexto.Bandas.Find(banda.IdBanda));
}
foreach (var banda in cliente.Bandas)
{
savedClient.Bandas.Add(contexto.Bandas.Find(banda.IdBanda));
}
contexto.Entry(savedClient).CurrentValues.SetValues(cliente);
contexto.SaveChanges();
}
}
Thanks Gert Arnold!!!
You don't really have to attach any object to the context. So you can prevent this exception by not doing that.
public void Update(Cliente cliente)
{
using (MegaStudioEntities contexto = new MegaStudioEntities())
{
Cliente savedClient = contexto.TipoClientes.Find(cliente.IdCliente);
foreach (var banda in savedClient.Bandas.ToList())
{
savedClient.Bandas.Remove(banda);
}
foreach (var banda in cliente.Bandas)
{
savedClient.Bandas.Add(banda);
}
savedClient.IdTipoCliente = cliente.IdTipoCliente;
savedClient.FechaModificacion = System.DateTime.Now;
Encriptar(cliente);
contexto.SaveChanges();
}
}
I'm not sure if this break code in Encriptar(cliente); because (obviously) I don't know what happens there.
As you see, you add and remove associations in a m:m relationship by adding/removing objects. You hardly ever (probably never) need to manipulate relationship state explicitly. If you feel a need to do that it most likely indicates that you overlook an easier way to achieve what you want.
I am having a real issue with the EF v1. I have quite a big EDMX with maybe 50 entities mapped, but this one entity is causing me grief.
The entity has mappings to other entities which in effect are reference tables, but for some reason it is trying to do an insert and not just update itself.
Here is a fragment of my code:
using (var context = new someEntities()) {
var studentCourseJoin =
context.StudentCourseJoinSet.Where(o => o.Code == scjCode).First();
studentCourseJoin.EntryStatus = new EntryStatus { Code = viewModel.StudentDetails.EntryStatusCode };
studentCourseJoin.ParentalInHigherEducation = new ParentalInHigherEducation { Code = viewModel.StudentDetails.ParentalInHigherEducationCode };
studentCourseJoin.School = new School { Code = viewModel.StudentDetails.SchoolCode };
studentCourseJoin.Institution = new Institution { Code = viewModel.StudentDetails.InstitutionCode };
studentCourseJoin.LastSchoolEndYear = viewModel.StudentDetails.LastSchoolEndYear;
studentCourseJoin.LastInstitutionEndYear = viewModel.StudentDetails.LastInstitutionEndYear;
// Blows up here trying to do an insert on the studentCourseJoin.Institution.
// But if I removed this one, then it will blow up on another one.
context.SaveChanges(true);
}
If anyone has ANY ideas please, they would help a lot.
Try adding those lines before calling SaveChanges:
ObjectStateEntry entry = context.ObjectStateManager.GetObjectStateEntry(studentCourseJoin);
entry.ChangeState(EntityState.Modified);
Update:
Try this for Institution instead:
studentCourseJoin.Institution = context.Institutions.FirstOrDefault(i => i.Code == viewModel.StudentDetails.InstitutionCode);