Basically I am mixing EF with one call to a stored procedure which does some batch deletions, otherwise EF is too slow.
Here is some pseudo-code of this scenario (I have more complex code in reality):
public void RemoveCustomer(int customerUID)
{
// this code is running in one db transaction
{
// retrieve certain orders of particular customer using EF
var orders = repoOrders.GetOrdersOfCustomer(filter, customerUID);
// do something with above orders before deletion using EF
repoX.DoSomethingWithOrders(orders);
// call SP to delete all orders of customer
repoOrders.DeleteAllOrdersOfCustomer(customerUID); // this calls a stored procedure
// delete customer using EF
repoCustomers.DeleteCustomer(customerUID); // throws exception due to relationship!
}
}
of course, customers-orders is one-to-many
(1:m) relation.
I want to avoid in the above scenario the exception which is thrown when there will be some orders loaded by the context belonging to the customer that gets deleted. Exception is:
"The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted."
So, I want to know if is possible to clear some/all orders from <DbSet>.Local
without causing any change into the database after calling the stored procedure and before user gets deleted.
I guess Detach could be used, but this means I should loop through.
What would you recommend?
Edit: I am new to EF and I am integrating EF now after the repositories were done using ADO.NET, and yes, the BL has been kept the same... so I try this integration with minimal efforts at this point.
Note: I can't make changes on the database structure.
Entity Framework has the following forms of caching built-in: Object caching – the ObjectStateManager built into an ObjectContext instance keeps track in memory of the objects that have been retrieved using that instance. This is also known as first-level cache.
The DbContext is a cache. Keeping hold of it for a long time is a terrible idea... it will slowly consume your application's memory hanging on to data that may well be stale. It was not designed to be used in the way you propose.
EF+ Query Cache opens up all caching features for Entity Framework Core users. To use caching, simply append to the query "FromCache" method before using an immediate resolution method like "ToList()" or "FirstOrDefault()".
dotnet ef dbcontext scaffold. Generates code for a DbContext and entity types for a database. In order for this command to generate an entity type, the database table must have a primary key.
I'd personally make each repository method use its own context, save its own changes at the end of the method, etc., and then use a TransactionScope
to ensure that the operations are atomic.
void DeleteAllOrdersOfCustomer(Guid customerUID)
{
using (var context = new Context())
{
...
context.SaveChanges();
}
}
...
using (var ts = new TransactionScope())
{
// call SP to delete all orders of customer
repoOrders.DeleteAllOrdersOfCustomer(customerUID); // this calls a stored procedure
// delete customer using EF
repoCustomers.DeleteCustomer(customerUID); // throws exception due to relationship!
ts.Complete();
}
This feature is available starting with Entity Framework Core 5!
To make the DbContext stop tracking all currently tracked entities:
myDbContext.ChangeTracker.Clear();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With