I need some idea in handling transactions in Entity Framework.
Let's consider a small example.
In my database I have a table A with auto generated identity column id, and I have a table B with a reference key to A(id).
In a scenario where I need to insert data in to both tables A and B, I want to start a transaction. Lets say a new row is inserted into A. I need newly inserted identity (id) value that I need to utilize for B insertion.
Can someone give me lead on handling this situation? Do we need to really utilize transactions in this case?
When you call SaveChanges, the updates are made in a transaction. If one fails, it is all rolled back. See here on msdn. Particularly the "Remarks" section.
Related
Background: I am writing an app and designing out the database using efcore. There are particular tables that store user actions that I need to keep track of who created the record, last modified it, and deleted it (soft deletes).
I have a user table that has an int as a PK and each of the respective field (CreatedBy, LastModifiedBy, DeletedBy) hold an int that points to a user row.
I do have a full audit setup where the entirety of a row has it's old/new contents stored on save and that works fine. But this particular question is about the more immediate created/modified/deleted by tracking.
Help desk is generally who uses these fields on a daily basis to help users determine whats going on quickly but there are a lot of places in the app itself that will draw upon those fields eventually (moreso created/modified from the app perspective).
Question: I was going to create a pk/fk relationship between the tables and the user table. However, it got me thinking about if there is a better strategy then adding those 3 fields and relationships to every single table going forward. Maybe a single table that stores the table name with its pk and created/modified/deleted columns that have a relationship back to the user table so that only 1 table has those pk/fk relationships back to user. I just feel that there must be a better way/more efficient way to handle this. Is there a better way to handle this?
Don't do what you are thinking, stick with your original design - keep all auditing fields as they related to each table on the table itself. Adding a table that stores auditing fields from other tables just creates a design nightmare.
Now, a bigger question is how to track the audit transaction. A design I like is as follows:
CreateBy. Add default binding SUBSTRING(SUSER_NAME(),1,50)
CreateTs. Add default binding GETDATE()
UpdateBy
UpdateTs
Hard deletes are allowed (i.e., bad data). Soft deletes come in the form of an additional column called ActiveInd (BIT) where that transaction would be stored as an Update. This means that Updates and soft Deletes are recorded into the UpdateBy/UpdateTs columns.
That should get you what you need if you intend on tracking activity from a web application. If you have a back-end system that is loading and manipulating data that I would include a LoadInfo table that tracks all of the jobs and then you can add both a LoadSequenceKey and ParentSequenceKey (add a self referencing foreign key here) and then you can create a foreign key on all tables that are modified by jobs that store the sequence key as either a CreateSequenceKey or UpdateSequenceKey.
Is there a way to invalidate a single entity such that the next time I ask for it, EF goes to the database for it?
Please note that I am not asking for any Refresh-Reload method. I just need to invalidate the cache such that in case this entity is needed again EF is forced to go to the database (only in case it is needed).
This is my concrete scenario (just if you have a couple of advises to me).
Lets suppose that I have a relationship in which a parent can have many children and the parent has properties that are summarized data about the children, e.g., Order.TotalQuantity.
If I insert, update, delete an OrderItem, I do it using a store procedure (that is mapped to these operations in EF). The aforementioned store procedures insert, update, and delete the OrderItem, but also update certain fields of the parent Order.
How am I supposed to handle this in EF? Do I "invalidate" the Order? If I ask for the Order before a call to SaveChanges the order would return with the wrong TotalQuantity anyway....
Thank you so much!!!
My C# application uses EF and calls min() on an int column to get the 'next' number in a sequence of numbers from a database table. The database table already has the next X numbers ready to go and my EF code just needs to get the 'next' one and after getting this number, the code then deletes that entry so the next request gets the following one etc. With one instance of the application all is fine, but with multiple users this leads to concurrency issues. Is there a design pattern for getting this next min() value in a serial fashion for all users, without resorting to a stored procedure? I'm using a mix of EF4.5 and EF5.
Thanks, Pete
Firstly, you can add an timestamp type column into your table and on Entity Framework property window set the concurrency mode to Fixed.
Doing that you enable optimistic concurrency check on the table. If there is another data context tries to interrupt your update, it will generate an excepton.
Check this link: http://blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concurrency-in-the-entity-framework.aspx?Redirected=true
Alternatively, you can use a TransactionScope object on your select/update logic. You can simply wrap around your code logic with a TransactionScope logic and everything within the scope will be enforced by the transaction.
Check this link for more information:
TransactionScope vs Transaction in LINQ to SQL
I'd like to know what is the best practice to track and/or persist changes over time if I use EF. I'd like to get started with EF for a new project. What I need is a kind of change history.
That's how I did it before: If a record was created it was saved with an ID and with the same ID as InvariantID. If the record was updated i marked it as deleted and created a new record with the new values and a new ID but the same InvariantID. Like this I always had my current record but a history of changes as well.
This works perfectly fine for my scenarios. The amount of historical records is not an issue because I use this usually only for data that's not changing very often.
Is this build in EF somehow or what's the best way to get this behavior for EF?
No it is not build into EF and it will not work this way. I even don't think that it is a good approach on the database level because it makes referential integrity very complex.
With EF this will work only if you use following approach:
You will use conditional mapping for your entity - condition will be IsDeleted = 0. It will ensure that only non deleted entities will be used in queries.
You will have mapped stored procedure for delete operation to correctly set IsDeleted = 1 instead of really deleting the record
You will have to manually call DeleteObject to delete your record and after that you will insert new record - the reason is that EF is not able to deal with scenario where entity change its PK value during update.
Your entities will not be able to participate in relations unless you manually rebuild referential integrity with some other stored procedure
You will need stored procedure to query historical (deleted) records
In an optimistic concurrency scenario fo a web-app, I am considering to give each table the timestamp column (sqlserver), comparable to a guid. Linq to entities will then generate sql update queries like WHERE id = #p0 AND timestamp = #p1 when one decorates the timestamp column with a certain attribute in Entity Framework. When the number of updated records returned is 0 we have detected a concurrency exception.
In a lot of posts I am reading about Self Tracking Entities which may be an alternative or better solution. But I didn't see any advantage over the "simple" timestamp method described above. Apart from the scenario where the database is immutable and doesn't offer the timestamp column.
Which solution is better and why?
EDIT
Yury Tarabanko correctly states that STE is another concept.
However zeeshanhirani's answer demonstrates that concurrency check is one main motive to track changes.
Lets rephrase the question: why would anybody use the STE concept for concurrency check where the 'timestamp column' method looks so much easier.
You are mixing two concepts here. STE is not about concurrency at all.
Self tracking entities just know how to do their change tracking regardles of how those changes were made. So you always know what is the current state of entities object graph. And you don't need to invoke additional change detecting.
What is STE.
EDIT:
"concurrency check is one main motive to track changes"
AFAIK STEs and POCOs share the same approach to concurrency check which simply results in additional where condition(s) in update statement sent to DB. Equivalent to this:
UPDATE [schema].[table]
SET [prop1] = value1, ...
WHERE [key] = key_value
AND [concurrency_prop_1] = concurrency_prop1_old_value
AND [concurrency_prop_2] = concurrency_prop2_old_value
So 'the main motive' to track changes is, well, to track changes in N-tier app.
Self Tracking Entity actually works with the concept you described. STE basically tracks changes to the object when the context is not around. However when it sends its changes back to the server using WCF service, it sends the current values of the property, the new state of the entity and also the original values of the the primary key column, independent association value and original value for any columns that are marked as Concurrency=Fixed in entity data model.