Intro
I'm developing an ASP.NET Core with SQL Server app that requires soft-delete on all records.
I'm using explicit BeginTransaction()
in case an entity is soft-deleted so that all related entities may be deleted as well.
Context
The reason I'm not doing it implicitly with just SaveChanges()
is when I use FromSqlInteroplated
to use some stored procedure to check if the entity has any related (not soft-deleted) entities; the results seems like they are from the actual database, but it does not work as I wanted, because I want to persist soft-delete changes before that stored procedure call is made.
Whereas when I use an explicit transaction with BeginTransaction()
and SaveChanges
after every delete operation, the stored procedure works as I want, even though at every SaveChanges
, the changes are NOT persisted to the actual database, it is made against the context, how is this happening?
Question
Sorry if it seems like a stupid question, if calling SaveChanges
will not persist changes against the actual db in an explicit uncommitted transaction context how does a stored procedure with FromSqlInteroplated
work in that case, is the stored procedure query made against the actual database or the context?
1条答案
按热度按时间kwvwclae1#
With an explicit transaction, calls to
SaveChanges
are written to the database and as far as any queries you execute with that DbContext against the database, it will see them. What happens with queries outside of that transaction scope will depend on the isolation level of the database and the external query in question. For instance if your database is using a typical READ COMMITTED isolation level, while the transaction is open, external queries will be blocked until the transaction is committed or rolled back. If the database is using something like READ COMMITTED SNAPSHOT (often recommended for EF and other ORMs) then those third party queries will not be blocked, they will simply return data that excludes changes being made by the transaction.For instance if I have a parent / child relationship and run the following:
With a breakpoint on the Rollback, if I check the results of
data
I will see that my new child "Dameon" is returned.AsNoTracking()
forces the query to the database. If you go to SSMS while this transaction is still running and runSELECT * FROM Children WHERE ParentId = 1
you would see all children except "Dameon" would be returned. He wouldn't appear in those results until the transaction is committed. After the rollback he won't appear in either queries. If you aren't using SNAPSHOT isolation then an SSMS query will be blocked by locks until the transaction is committed or rolled back.If you want proof the row is in the database, you can use
SELECT * FROM Children WHERE ParentId = 1 WITH (UNCOMMITTED)
and "Dameon" appears.