How do i delete single record from table using EF 6.1.1 - entity-framework

I am using Entity Framework 6.1.1.
I am deleting single record from table as following but i am not sure whether its the only way or could further rewrite it in an efficient way.
Can someone share comments?
Reason: I am asking because many solutions in earlier posts are referring to EF 4.0 and not using the latest version 6.1.1.
Guid studentId = student.Id;
StudentReportDetail stuDetails = _context.StudentReportDetail.Find(studentId);
if (stuDetails != null)
{
_context.StudentReportDetail.Remove(stuDetails);
_context.SaveChanges();
}

There are no changes about how to delete an entity between EF 4 and EF 6. To delete an entity using Entity Framework, you need to use the Remove method on DbSet. Remove works for both existing and newly added entities.
Calling Remove on an entity that has been added but not yet saved
to the database will cancel the addition of the entity. The entity is
removed from the change tracker and is no longer tracked by the
DbContext.
Calling Remove on an existing entity that is being change-tracked
will register the entity for deletion the next time SaveChanges is
called.
Deleting with loading from the database
As the example you show in your question, you need to load first the existing entity from your context to delete it. If you don't know the Id, you can execute a query as I show below to find it first:
var report= (from d in context.StudentReportDetail
where d.ReportName == "Report"
select d).Single();
context.StudentReportDetail.Remove(report);
context.SaveChanges();
Deleting without loading from the database
If you need to delete an entity, but it’s not already in memory, it’s a little inefficient to retrieve that entity from the database just to delete it. If you know the key of the entity you want to delete, you can attach a stub that represents the entity to be deleted, and then delete this stub. A stub is an instance of an entity that just has the key value assigned. The key value is all that’s required for deleting entities.
var toDelete = new StudentReportDetail {Id = 2 };
context.StudentReportDetail.Attach(toDelete);
context.StudentReportDetail.Remove(toDelete);
context.SaveChanges();
Other way could be changing the entity's state to Deleted.DbContext has methods called Entry and Entry<TEntity>, these methods get a DbEntityEntry for the given entity and provide access to the information about the entity and return a DbEntityEntry object able to perform the action on the entity. Now you can perform the delete operation on the context by just changing the entity state to EntityState.Deleted:
var toDelete = new StudentReportDetail {Id = 2 };
context.Entry(toDelete).State = EntityState.Deleted;
context.SaveChanges();
Using a 3rd party library
There is another way but is using a 3rd party library, EntityFramework Plus, there is a nugget package you can install. You can use the batch delete operation:
context.StudentReportDetail
.Where(u => u.Id== stuDetails)
.Delete();

Related

How to use EF core owned entites

I am using a SQLite database EFCore 2.0 preview in UWP Project.
The address table is split into to different entities
Delivery address,
Invoice Address
using
modelBuilder.Entity<Project>().OwnsOne(p => p.DeliveryAddress);
which works great for setting up the database, with migrations, creates the different table in the database. With test data that I have put in manually works great at reading data from these tables. But how do I save changes to the DeliveryAddress table. Nothing is getting persisted to the database, when I save the using:
public void UpdateDeliveryAddress(Project modifiedProject)
{
using (var db = new SteelFrameCalculatorDataContext())
{
db.Entry(modifiedProject).State = EntityState.Modified;
db.SaveChanges();
}
}
Project being the parent entity
2017-06-11T23:21:10.9242463+01:00 Warning 8 Microsoft.EntityFrameworkCore.Model.Validation
The key {'ProjectId'} on entity type 'Project.DeliveryAddress->Address' contains properties in shadow state - {'ProjectId'}. To configure this warning use the DbContextOptionsBuilder.ConfigureWarnings API (event id 'CoreEventId.ModelValidationShadowKeyWarning'). ConfigureWarnings can be used when overriding the DbContext.OnConfiguring method or using AddDbContext on the application service provider.
Using the following allowed in to save updates to the database. Assume the UpdateRange(entity) sets all to modified. Not sure if this is the correct way, but it works.
using (var db = new SteelFrameCalculatorDataContext())
{
db.UpdateRange(modifiedProject);
db.SaveChanges();
}
Have you tried setting the state of the child object? Looks like you're only setting the parent Project state.
Adding this should do it:
db.Entry(modifiedProject.DeliveryAddress).State = EntityState.Modified;
db.Entry(modifiedProject).Reference(a=>a.DeliveryAddress).TargetEntry.State = EntityState.Modified;

Entity Framework 5 Foreign Key New Record on SaveChanges

I'm using .NET4.5/EF5 and have created the model from an existing database.
I'm using the following code:
Order currentOrder = new Order();
using (var db = new ILSEntities())
{
try
{
Event currentEvent = db.Events.OrderByDescending(u => u.EventID).FirstOrDefault();
currentOrder.Event = currentEvent;
db.Orders.Add(currentOrder);
db.SaveChanges();
And I'm seeing that a duplicate record is being created of the Event object I find, which is not what I wanted to happen.
I've read a lot of posts relating to similar problems, but where the context of the two participants in the foreign key relationships are different. Here, I'm saving with the same context I use to find one, and the other object is new.
I've also tried:
currentOrder.Event.EventID = currentEvent.EventID;
but that fails as well as I get an EF validation error telling me it needs values for the other members of the Event object.
I've also tried specifically setting the EntityState of the object being duplicated to Detached, Modified etc. after adding the Order object but before SaveChanges without success.
I'm sure this is a basic problem, but it's got me baffled
In my understanding, both parent and child objects have to be in the context before you assign any relationship between them to convince the entity framework that an entity exists in the database already. I guess you are trying to add new Order object to Database, to add new object you should be using AddObject method, Add() method is used to establish relation between entitties. In your code, currentOrder is not in the context. Try to hook it in the same context and then assign a relation. Your code should look like this :
Order currentOrder = new Order();
using (var db = new ILSEntities())
{
try
{
Event currentEvent = db.Events.OrderByDescending(u => u.EventID).FirstOrDefault();
db.Orders.Attach(currentOrder); //attach currentOrder to context as it was not loaded from the context
currentOrder.Events.Add(currentEvent);//establish relationship
db.ObjectStateManager.ChangeObjectState(currentOrder, EntityState.Added);
db.SaveChanges();
}
}
OK, I did in the end figure this out, and it was my fault.
The problem was that the Order object is FK'd into another table, Shipments, which is also FK'd into Events. The problem was that it was the Event reference in the Shipment object that was causing the new record. The solution was to let EF know about these relationships by adding them all within the same context.
The code assembling the object graph was spread over a number of webforms and the responses here made me take a step back and look at the whole thing critically so whilst no one of these answers is correct, I'm voting everybody who replied up

Entity framework: how to read current data after delete from referenced table

I have three tables Job, Contact and a reference table between them named JobContact. When I delete a record from JobContact table, so record is deleted from database, but it is still present in code. I mean, when I do a select Job by key and when I'm accessing job.JobContact, so record is still there.
How can I force EF to get the current data from this table?
Edited:
I'm using EF to delete the record. Here is a code sample how I'm doing it:
Step 1: delete record from JobContact:
var jobContactRepos = RepositoryFactory.GetRepository<JobContact>();
var jobContact = jobContactRepos.SelectByKey(jobContactId);
jobContactRepos.Delete(jobContact);
jobContactRepos.Save();
Step 2: get the job record from DB after step 1 is done:
var jobRepos = RepositoryFactory.GetRepository<Job>();
var job = jobRepos.SelectByKey(id);
After Step 1, record is deleted from DB: it is OK.
After Step 2, record is still present in the job.JobContact entity: it is not OK.
RepositoryFactory creates already a new context. So I don't understant. In which place in my code should I use Refresh() method?
thanks
You can dispose your EF context and create a new one, this will force EF to get fresh data from the DB instead of using possibly cached data. Alternatively you can call Refresh() on your context using RefreshMode.StoreWins.
But the real question is why do you delete this record from the database directly and don't use EF for it? Had you used the EF context to remove the Contact entity from the Contacts navigation property collection of your Job entity, this problem shouldn't be there in the first place.
Edit:
The reference table should be represented in EF as a navigation property Contacts in your Job entities, and a navigation property Jobs in your Contact entities. Are you using an older version of EF (I am probably not familiar enough with previous versions) or have a custom repository layer that introduces this reference entity?

Entity Framework / EF4: Multiple inserts of related entities in a transactionscope

I have a similar problem.
I want to make two inserts in the same transactionscope. The objects are related and have a FK relationship between them, but for several reasons I do not want to connect them via the navigation property, but only by ID.
This is a simplification of what I what I want to accomplish:
Order o = new Order();
OrderDetails d = new OrderDetails();
new Repository().SaveNew(o, d);
class Repository{
void SaveNew(Order o, OrderDetails d){
using (TransactionScope transaction = new TransactionScope())
{
_context.Connection.Open();
// order
_context.Orders.ApplyChanges(o);
_context.SaveChanges();
// details
d.OrderID = o.ID;
_context.OrderDetails.ApplyChanges(d);
_context.SaveChanges(); <--- UpdateException
_context.Connection.Close();
transaction.Complete();
}
}
}
The problem is that I get an UpdateException because the FK evaluation fails. I tried to remove the FK relationship and running the exact same piece of code, and it worked fine, and both objects had the right properties set. So why does this approach fail? And how should this instead be done? Again, I do not want to attach the entites via their navigation properties.
Thank you!
I would leave the FK relationship in the database, but delete the AssociationSet and Association from the SSDL. The designer won't let you do this, you have to edit the XML manually.
I am using EF 4 btw.
Then use AddObject and SaveChanges in your SaveNew method to add the first (parent) object. Set the foreign key Property on the child and add it with AddObject and SaveChanges.
I do not have development environment running to test this, but what I think is happening is:
Assuming that the id is generated in the database. At the point when you save the order you do not know the ID.
Then the order ID of the order detail is set to the ID of the order, but the order was not reloaded from the database. I suspect that the value is 0.
When you try to save the order detail with FK of 0, you get an error.
Either save both at the same time so that EF does the work for you, or reload the order.

Entity Framework DeleteObject child

What is the best way to delete an object (and its child objects) using EF? I'd like to pass just the id for the object to delete, and have EF handle deleting its dependent data (foreign key'd data). Do I have to retrieve the object first based on the id and then call "DeleteObject"?
If you have cascade configured in the database, then deleting the principle should be enough.
You can do this without a query to the database to GET the thing to be deleted using Stub entities like this:
var stub = new Principal{ID = idToDelete};
ctx.AttachTo("PrincipalsEntitySetName", stub);
ctx.DeleteObject(stub);
Of course this is not the whole story if there are references or fields used for concurrency checks you will need those too.
If on the other hand you only have a cascade delete in the model (i.e. there is no cascade in the database) you will need to get ALL the dependents in memory first, and then call delete:
var stub = new Principal{ID = idToDelete};
ctx.AttachTo("PrincipalsEntitySetName", stub);
stub.Dependendents.Load();
ctx.DeleteObject(stub);
This only works because the EF issues (what it expects to be ) redundant deletes to keep the ObjectContext in sync with what it expects to happen in the database.
Hope this helps
Alex
PS I have some tips on this topic on my MSDN blog. Check out tip 33 (cascade delete) and tip 26 (stub entities)