I am using Entity Framework Core 3.1 with SQL Server.
I search how update column only for modified properties of a disconnected entity like :
public void UpdateOrderCustomer(int orderId, string customerName)
{
var order = new Order { Id = orderId };
using(var context = new MyDbContext())
{
context.Update(order);
order.Customer = customerName;
context.SaveChanges();
}
}
But this updates all order's column.
One solution is to load entity before update properties like :
public void UpdateOrderCustomer(int orderId, string customerName)
{
using(var context = new MyDbContext())
{
var order = context.Orders.Single(o => o.Id == orderId);
order.Customer = customerName;
context.SaveChanges();
}
}
But to load the entity, this executes an additional useless query.
I hoped there would be a BeginTracking method, but I haven't found this or any similar functionality.
How to update columns only for modified properties from a disconnected entity?
You can update a single property or a deattached entity like so:
public void ChangePassword(int userId, string password)
{
var user = new User() { Id = userId, Password = password };
using (var db = new MyEfContextName())
{
db.Users.Attach(user);
db.Entry(user).Property(x => x.Password).IsModified = true;
db.SaveChanges();
}
}
I've got an Entity Model containing a list that is type of another Entity model, I need to add a record with a list of the other model to the Database at once
a null reference exception occurs when I'm adding each prop to prop list with ForEach
public IActionResult RegisterUnitConfirm(InventoryItemUnitViewModel model)
{
if (ModelState.IsValid)
{
InventoryItemUnit unit = new InventoryItemUnit()
{
Title = model.Title,
Item_Id = model.Item_Id,
};
model.Props.ForEach(x => unit.Props.Add(new InventoryItemUnitProp()
{
Name = x.Name,
Value = x.Value,
Category_Id = x.Category_Id,
}));
DB.Add(unit);
if (DB.SaveChanges() != 0)
{
TempData["GlobalSuccess"] = "";
return RedirectToAction("UnitSummery");
}
TempData["GlobalError"] = "";
return RedirectToAction("UnitSummery");
}
TempData["GlobalError"] = "Model State is invalid";
return RedirectToAction("UnitSummery");
}
you should create new Props when create new unit
like this :
InventoryItemUnit unit = new InventoryItemUnit()
{
Title = model.Title,
Item_Id = model.Item_Id,
Props=new List<Props>()
};
I hope it will be useful
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'm trying to update an entity and I've run into the following error:
InvalidOperationException: The instance of entity type 'BookLoan'
cannot be tracked because another instance of this type with the same
key is already being tracked. When adding new entities, for most key
types a unique temporary key value will be created if no key is set
(i.e. if the key property is assigned the default value for its type).
If you are explicitly setting key values for new entities, ensure they
do not collide with existing entities or temporary values generated
for other new entities. When attaching existing entities, ensure that
only one entity instance with a given key value is attached to the
context.
I've done a little research and from what I can tell I'm apparently trying to track an already tracked entity when I use _context.Update(bookloan); but I'm not really sure what to do.
What I'm trying to do is update an existing entity/record in my database. Here are the get and post controllers as I'm not sure what else to share.
Get
[HttpGet]
public async Task<IActionResult> Return(int? id)
{
if (id == null)
{
return NotFound();
}
if (isBookCheckedOut(id) == false)
{
//Not checked out
return RedirectToAction("Index");
}
else
{
var bookloan = (from book in _context.Books.Where(b => b.BookId == id)
join loan in _context.BookLoans.Where(x => !x.ReturnedOn.HasValue) on book.BookId equals loan.BookID into result
from loanWithDefault in result.DefaultIfEmpty()
select new BookReturnViewModel
{
BookLoanID = loanWithDefault.BookLoanID,
BookID = book.BookId,
Title = book.Title,
StudentID = loanWithDefault == null ? null : loanWithDefault.StudentID,
StudentFristName = loanWithDefault == null ? null : loanWithDefault.Student.FirstName,
StudentLastName = loanWithDefault == null ? null : loanWithDefault.Student.LastName,
//Fines
CheckedOutOn = loanWithDefault == null ? (DateTime?)null : loanWithDefault.CheckedOutOn,
IsAvailable = loanWithDefault == null,
AvailableOn = loanWithDefault == null ? (DateTime?)null : loanWithDefault.DueOn
}).FirstOrDefault();
if (bookloan == null)
{
return NotFound();
}
return View(bookloan);
}
}
Post:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Return(BookReturnViewModel model)
{
if (ModelState.IsValid && isBookCheckedOut(1) == true)
{
var bookloan = new BookLoan()
{
BookLoanID = model.BookLoanID,
BookID = model.BookID,
StudentID = model.StudentID,
CheckedOutOn = (DateTime)model.CheckedOutOn,
DueOn = (DateTime)model.AvailableOn,
ReturnedOn = DateTime.Now
};
try
{
_context.Update(bookloan);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
}
return RedirectToAction("Index");
}
else
{
}
return View();
}
Your context already includes the entity, so rather that creating a new one, get the existing one based on the ID of the entity and update its properties, then save it
if (ModelState.IsValid && isBookCheckedOut(1) == true)
{
// Get the existing entity
BookLoan bookLoan = db.BookLoans.Where(x => x.BookLoanID == model.BookLoanID).FirstOrDefault();
if (bookLoan != null)
{
bookLoan.BookID = model.BookID;
bookLoan.StudentID = model.StudentID;
.... // update other properties as required
_context.Update(bookloan);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
....
Side note: when returning the view, its good practice to pass back the model using return View(model); - your form controls will be correctly populated even if you don't (because they take the values from ModelState), but if you have any references to the model properties (e.g. <div>#Model.someProperty</div>) it would throw an exception.
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();
}