I have a SQL Server table in Entity Framework named employ with a single key column named ID.
How do I delete a single record from the table using Entity Framework?
It's not necessary to query the object first, you can attach it to the context by its id.
Like this:
var employer = new Employ { Id = 1 };
ctx.Employ.Attach(employer);
ctx.Employ.Remove(employer);
ctx.SaveChanges();
Alternatively, you can set the attached entry's state to deleted :
var employer = new Employ { Id = 1 };
ctx.Entry(employer).State = EntityState.Deleted;
ctx.SaveChanges();
You can use SingleOrDefault to get a single object matching your criteria, and then pass that to the Remove method of your EF table.
var itemToRemove = Context.Employ.SingleOrDefault(x => x.id == 1); //returns a single item.
if (itemToRemove != null) {
Context.Employ.Remove(itemToRemove);
Context.SaveChanges();
}
var stud = (from s1 in entities.Students
where s1.ID== student.ID
select s1).SingleOrDefault();
//Delete it from memory
entities.DeleteObject(stud);
//Save to database
entities.SaveChanges();
Employer employer = context.Employers.First(x => x.EmployerId == 1);
context.Customers.DeleteObject(employer);
context.SaveChanges();
I am using entity framework with LINQ. Following code was helpful for me;
1- For multiple records
using (var dbContext = new Chat_ServerEntities())
{
var allRec= dbContext.myEntities;
dbContext.myEntities.RemoveRange(allRec);
dbContext.SaveChanges();
}
2- For Single record
using (var dbContext = new Chat_ServerEntities())
{
var singleRec = dbContext.ChatUserConnections.FirstOrDefault( x => x.ID ==1);// object your want to delete
dbContext.ChatUserConnections.Remove(singleRec);
dbContext.SaveChanges();
}
More generic approuch
public virtual void Delete<T>(int id) where T : BaseEntity, new()
{
T instance = Activator.CreateInstance<T>();
instance.Id = id;
if (dbContext.Entry<T>(entity).State == EntityState.Detached)
{
dbContext.Set<T>().Attach(entity);
}
dbContext.Set<T>().Remove(entity);
}
Just wanted to contribute the three methods I've bounced back and forth with.
Method 1:
var record = ctx.Records.FirstOrDefault();
ctx.Records.Remove(record);
ctx.SaveChanges();
Method 2:
var record = ctx.Records.FirstOfDefault();
ctx.Entry(record).State = EntityState.Deleted;
ctx.SaveChanges();
ctx.Entry(record).State = EntityState.Detached;
One of the reasons why I prefer to go with Method 2 is because in the case of setting EF or EFCore to QueryTrackingBehavior.NoTracking, it's safer to do.
Then there's Method 3:
var record = ctx.Records.FirstOrDefault();
var entry = ctx.Entry(record);
record.DeletedOn = DateTimeOffset.Now;
entry.State = EntityState.Modified;
ctx.SaveChanges();
entry.State = EntityState.Detached;
This utilizes a soft delete approach by setting the record's DeletedOn property, and still being able to keep the record for future use, what ever that may be. Basically, putting it in the Recycle Bin.
Also, in regards to Method 3, instead of setting the entire record to being modified:
entry.State = EntityState.Modified;
You would also simply set only the column DeletedOn as modified:
entry.Property(x => x.DeletedOn).IsModified = true;
With Entity Framework 6, you can use Remove.
Also it 's a good tactic to use using for being sure that your connection is closed.
using (var context = new EmployDbContext())
{
Employ emp = context.Employ.Where(x => x.Id == id).Single<Employ>();
context.Employ.Remove(emp);
context.SaveChanges();
}
[HttpPost]
public JsonResult DeleteCotnact(int id)
{
using (MycasedbEntities dbde = new MycasedbEntities())
{
Contact rowcontact = (from c in dbde.Contact
where c.Id == id
select c).FirstOrDefault();
dbde.Contact.Remove(rowcontact);
dbde.SaveChanges();
return Json(id);
}
}
What do you think of this, simple or not, you could also try this:
var productrow = cnn.Product.Find(id);
cnn.Product.Remove(productrow);
cnn.SaveChanges();
Using EntityFramework.Plus could be an option:
dbContext.Employ.Where(e => e.Id == 1).Delete();
More examples are available here
u can do it simply like this
public ActionResult Delete(int? id)
{
using (var db = new RegistrationEntities())
{
Models.RegisterTable Obj = new Models.RegisterTable();
Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
if (personalDetail == null)
{
return HttpNotFound();
}
else
{
Obj.UserID = personalDetail.UserID;
Obj.FirstName = personalDetail.FName;
Obj.LastName = personalDetail.LName;
Obj.City = personalDetail.City;
}
return View(Obj);
}
}
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int? id)
{
using (var db = new RegistrationEntities())
{
Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
db.RegisterDbTable.Remove(personalDetail);
db.SaveChanges();
return RedirectToAction("where u want it to redirect");
}
}
model
public class RegisterTable
{
public int UserID
{ get; set; }
public string FirstName
{ get; set; }
public string LastName
{ get; set; }
public string Password
{ get; set; }
public string City
{ get; set; }
}
view from which u will call it
<table class="table">
<tr>
<th>
FirstName
</th>
<th>
LastName
</th>
<th>
City
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td> #item.FirstName </td>
<td> #item.LastName </td>
<td> #item.City</td>
<td>
Edit |
Details |
Delete
</td>
</tr>
}
</table>
i hope this will be easy for u to understand
You can do something like this in your click or celldoubleclick event of your grid(if you used one)
if(dgEmp.CurrentRow.Index != -1)
{
employ.Id = (Int32)dgEmp.CurrentRow.Cells["Id"].Value;
//Some other stuff here
}
Then do something like this in your Delete Button:
using(Context context = new Context())
{
var entry = context.Entry(employ);
if(entry.State == EntityState.Detached)
{
//Attached it since the record is already being tracked
context.Employee.Attach(employ);
}
//Use Remove method to remove it virtually from the memory
context.Employee.Remove(employ);
//Finally, execute SaveChanges method to finalized the delete command
//to the actual table
context.SaveChanges();
//Some stuff here
}
Alternatively, you can use a LINQ Query instead of using LINQ To Entities Query:
var query = (from emp in db.Employee
where emp.Id == employ.Id
select emp).Single();
employ.Id is used as filtering parameter which was already passed from the CellDoubleClick Event of your DataGridView.
Here's a safe way:
using (var transitron = ctx.Database.BeginTransaction())
{
try
{
var employer = new Employ { Id = 1 };
ctx.Entry(employer).State = EntityState.Deleted;
ctx.SaveChanges();
transitron.Commit();
}
catch (Exception ex)
{
transitron.Rollback();
//capture exception like: entity does not exist, Id property does not exist, etc...
}
}
Here you can pile up all the changes you want, so you can do a series of deletion before the SaveChanges and Commit, so they will be applied only if they are all successful.
The best way is to check and then delete
if (ctx.Employ.Any(r=>r.Id == entity.Id))
{
Employ rec = new Employ() { Id = entity.Id };
ctx.Entry(rec).State = EntityState.Deleted;
ctx.SaveChanges();
}
For a generic DAO this worked:
public void Delete(T entity)
{
db.Entry(entity).State = EntityState.Deleted;
db.SaveChanges();
}
Related
I'm making a simple WPF application that uses one table in a DB. I'm using Entity Framework. Here's how I add my new record:
public static bool CreateNew(CustomerModel newCustomer)
{
var addCustomer = new Customer
{
ID = newCustomer.ID,
Name = newCustomer.Name,
Address = newCustomer.Address,
City = newCustomer.City,
Country = newCustomer.Country
};
try
{
//_context.Customers.Add(addCustomer);
_context.Entry(addCustomer).State = EntityState.Added;
_context.SaveChanges();
return true;
}
catch
{
return false;
}
}
Works fine: record appears in DB.
Now I try to delete the record that was just added based on its ID:
public static bool Delete(long id)
{
var cust = new Customer() { ID = id };
try
{
_context.Entry(cust).State = EntityState.Deleted;
/*_context.Customers.Attach(cust);
_context.Customers.Remove(cust);*/
_context.SaveChanges();
return true;
}
catch
{
return false;
}
}
Doesn't work.
It seems like the DbSet within the application does not hold the entry that was added to the DB. How do I fix this?
PS. Customer class is my POCO entity and CustomerModel is the class I use for the application. _context references the DbContext Entity Framework uses
Try this instead. Use Find method like this:
var cust = _context.Customers.Find(id);
_context.Customers.Remove(cust);
_context.SaveChanges();
I have three tables
News
NewsCategory
Category
When I create a new News item, I need to assign categories to that new item.
My code looks like that
var NewsToSave = new News();
NewsToSave.NewsBody = model.NewsBody;
NewsToSave.NewsTitle = model.NewsTitle;
NewsToSave.NewsImagePath = NewsImagePath;
NewsToSave.NewsDate = System.DateTime.Now;
db.News.Add(NewsToSave);
db.SaveChanges();
foreach (var id in SelectedIDs)
{
// How to assign selected categories to NewsToSave object and save the Ids in the middle table
}
How to assign selected categories to NewsToSave object?
Thank you
You could override your context this way:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<NewsToSave>()
.HasMany(c => c.Categories).WithMany(i => i.NewsToSaves)
.Map(t => t.MapLeftKey("NewsToSaveID")
.MapRightKey("CategoryID")
.ToTable("NewsCategory"));
}
And process the added data:
void AddOrUpdateNews(Context context, int categoryId, string newsTitle)
{
var cat = context.Categories.SingleOrDefault(c => c.Id == categoryId);
var nws = cat.News.SingleOrDefault(n => n.Title == newsTitle);
if(nws == null)
{
cat.News.Add(context.News.SingleOrDefault(c => c.Title == newsTitle));
}
}
This worked great on the ASP.NET application I made a few months ago. Hope it can help you out.
You can create a category for each id, attach it (provided that it exists in the db already) and then add it to the Categories list of the news and save:
foreach(var id in SelectedIDs)
{
var category = new Category { CategoryId == id};
db.Categories.Attach(category);
NewsToSave.Add(category);
}
db.News.Add(NewsToSave);
db.SaveChanges();
foreach (var id in SelectedIDs)
{
// You have to load the category from Db
var cat = db.Categories.FirstOrDefault(x=> c.Id == id);
// Added to the NewsToSave
if (cat !=null)
NewsToSave.Categories.Add(cat);
}
// Store the changes
db.SaveChanges();
I am getting following exception on my project:
An exception of type 'System.InvalidOperationException' occurred in
EntityFramework.dll but was not handled in user code
Additional information: Saving or accepting changes failed because of
more than one entity of type 'MyProject.Data.Poco.MyProjectCountry' have the
same primary key value. Ensure that explicitly set primary key values
are unique. Ensure that database-generated primary keys are configured
correctly in the database and in the Entity Framework model. Use the
Entity Designer for Database First/Model First configuration. Use the
'HasDatabaseGeneratedOption" fluent API or
'DatabaseGeneratedAttribute' for Code First configuration.
the error happens at the following line:
using (MyProjectDataContext context = new MyProjectDataContext())
{
MyProjectItemTag existingItemTag = (from p in context.ItemTags.Include(p => p.MyProjectGenre).Include(p => p.MyProjectCountry)
where p.MyProjectUser.UserId == ItemTag.MyProjectUser.UserId &&
p.MyProjectItem.ItemId == MyProjectItem.ItemId
select p).FirstOrDefault();
// new tag
if (existingItemTag == null)
{
existingItemTag = ItemTag;
existingItemTag.MyProjectItem.ItemId = MyProjectItem.ItemId;
}
// existing tag
else
{
existingItemTag.MyProjectItem = new MyProjectItem { ItemId = MyProjectItem.ItemId };
existingItemTag.MyProjectUser = new MyProjectUser { UserId = ItemTag.MyProjectUser.UserId };
}
// updates
existingItemTag.MyProjectCountry = MyProjectCountry;
if (MyProjectCountry != null)
existingItemTag.MyProjectCountry = new MyProjectCountry()
{
MyProjectCountryId = MyProjectCountry.MyProjectCountryId
};
existingItemTag.MyProjectGenre = MyProjectGenre;
context.Entry(existingItemTag.MyProjectItem).State = EntityState.Unchanged;
context.Entry(existingItemTag.MyProjectUser).State = EntityState.Unchanged;
context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;
context.Entry(existingItemTag.MyProjectGenre).State = EntityState.Unchanged;
if (existingItemTag.MyProjectCountry != null)
{
context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;
}
// db
context.ItemTags.AddOrUpdate(existingItemTag);
context.SaveChanges();
return existingItemTag.ItemTagId;
}
context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;
My Class:
public class MyProjectItemTag
{
public int ItemTagId { get; set; }
public MyProjectUser MyProjectUser { get; set; }
public MyProjectItem MyProjectItem { get; set; }
public MyProjectCountry MyProjectCountry { get; set; }
public MyProjectGenre MyProjectGenre { get; set; }
public MyProjectMood MyProjectMood { get; set; }
public MyProjectItemTag()
{
}
public MyProjectItemTag(string userId, string providerContentId)
{
MyProjectUser = new MyProjectUser
{
UserId = userId
};
MyProjectItem = new MyProjectItem
{
ProviderContentId = providerContentId
};
}
}
My Config:
public class MyProjectItemTagConfiguration : EntityTypeConfiguration<MyProjectItemTag>
{
public MyProjectItemTagConfiguration()
{
ToTable("MyProjectItemTags");
HasKey(p => p.ItemTagId);
HasRequired(p => p.MyProjectUser);
HasRequired(p => p.MyProjectItem);
HasOptional(p => p.MyProjectCountry);
}
}
What I am missing here?
This is all you really need to look for:
Additional information: Saving or accepting changes failed because more than one entity of type 'MyProject.Data.Poco.MyProjectCountry' have the same primary key value.
The following code may not necessarily populate the MyProjectCountry.
MyProjectItemTag existingItemTag =
(from p in context.ItemTags
.Include(p => p.MyProjectGenre)
.Include(p => p.MyProjectCountry)
where p.MyProjectUser.UserId == ItemTag.MyProjectUser.UserId
&& p.MyProjectItem.ItemId == MyProjectItem.ItemId
select p).FirstOrDefault();
So you set it to some variable you haven't give us any context too...
existingItemTag.MyProjectCountry = MyProjectCountry;
I'd assume it is not null, so you change it's ID which is a Giant Code Smell...
(Why assign it? after all it's already assigned..)
if (MyProjectCountry != null)
existingItemTag.MyProjectCountry = new MyProjectCountry()
{
MyProjectCountryId = MyProjectCountry.MyProjectCountryId
};
Then you tell EF it hasn't changed?? Another Code Smell.
context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;
So what this tells me is that the Context has already downloaded this entity into its Object Cache, but the one you are assigning is not the one in the cache so when I tries to added to the cache, there is a duplicate.
Try to use context.Model.AddORUpdate(model) Method, you need to add using System.Data.Entity.Migrations as well for this method.
Check in the.edmx file StoreGeneratedPattern. If the Id in the database is auto generated, StoreGeneratedPattern has to be Identity. In my case was None. It's not the best practice to edit the edmx file. I personally deleted the table in the edmx file, I created a new one and after that the StoreGeneratedPattern = Identity.
I am getting the following error message when I try to update my data back to the table:
Attaching an entity of type 'Namespace.Models.Child' 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.
Like usual I am guessing it is something simple but I am not sure where the issue is.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ParentsCreateVM viewModel)
{
if (ModelState.IsValid)
{
var parent = new Parent()
{
FirstName = viewModel.FirstName,
LastName = viewModel.LastName,
ParentID = viewModel.ParentID
};
//db.Parents.Add(parent);
db.Entry(parent).State = EntityState.Modified;
foreach (ChildVM item in viewModel.Children)
{
var child = new Child()
{
Name = item.Name,
DOB = item.DOB,
Address = item.Address,
ParentID = viewModel.ParentID,
ChildID = item.ChildID
};
db.Entry(child).State = child.ChildID == 0 ?
EntityState.Added :
EntityState.Modified;
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
Exception is clear, dbcontext already has load the same child item.
I suggest you do this way
//find child item in db
var child = db.Entry<Child>().Single(child=>child.key== value);
//then chang value
child.Name = item.Name;
child.DOB = item.DOB;
child.Address = item.Address;
I have the following code and I cannot achieve saving the changes.
The parameter of my method is a string containing the RefCode of a product I want to modify in the database, then the query is pulling the BaseProduct that is supposed to be modified.
(I tried to simplify the code and set it in English, so I have probably introduced some syntactic errors, but in my code in debug mode, I get all the info FROM the DB). Is there something wrong with the "select new" in the Linq query ?
public static void UpdateProduct(ViewProduct productToUpdate)
{
using (var context = new my_Entities())
{
var BaseProduct = (from prod in context.Product
where prod.Ref == productToUpdate.BaseProduct.RefPrd
select new ViewBaseProduct
{
RefPrd = prod.Ref,
DescrPrd = prod.DescrPrd,
NormeCe = (bool)prod.NormeCE
}).FirstOrDefault();
if (BaseProduct != null)
{
//BaseProduct.NormeCe = false;
BaseProduct = productToUpdate.BaseProduct;
context.SaveChanges();
}
}
}
But BaseProduct is a ViewBaseProduct object, is ViewBaseProduct a entity class? It seems it is a ViewModel class.
You have to get de Product entity, modify his fields and savechanges. It seems you only apply changes to the ViewModel class.
Try this:
public static void UpdateProduct(ViewProduct productToUpdate)
{
using (var context = new my_Entities())
{
var BaseProduct = (from prod in context.Product
where prod.Ref == productToUpdate.BaseProduct.RefPrd)
.FirstOrDefault();
if (BaseProduct != null)
{
//BaseProduct.NormeCe = false;
BaseProduct.field1 = productToUpdate.BaseProduct.field1;
BaseProduct.field2 = productToUpdate.BaseProduct.field2;
//update the necesary fields
//......
context.SaveChanges();
}
}
}
This won't work that way. You should use the CurrentValues.SetValues() method:
contexte.Entry(BaseProduct).CurrentValues.SetValues(productToUpdate.BaseProduct);
I think you have to Try this
public static void UpdateProduct(ViewProduct productToUpdate)
{
using (var contexte = new my_Entities())
{
var BaseProduct = (from prod in contexte.Product
where prod.Ref == productToUpdate.BaseProduct.RefPrd
select new ViewBaseProduct
{
RefPrd = prod.Ref,
DescrPrd = prod.DescrPrd,
NormeCe = (bool)prod.NormeCE
}).FirstOrDefault();
if (BaseProduct != null)
{
BaseProduct.BaseProduct.RefPrd=productToUpdate.BaseProduct.RefPrd
BaseProduct.BaseProduct.DescrPrd=productToUpdate.BaseProduct.DescrPrd
BaseProduct.BaseProduct.NormeCE==(bool)productToUpdate.BaseProduct.NormeCE
contexte.SaveChanges();
}
}
}