I'm new in Entity Framework and i have problem with something which was quite easy in pure t-sql. Assume that we have table with 3 columns. Id(identity, primary key), IdKind (int), Number(int). Column Nubmer depends on IdKind column. Data in this table should look like this:
Id | IdKind | Number
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 1
5 | 2 | 2
6 | 2 | 3
As you can see column number is auto incremented depends on IdKind. In t-sql I was finding max(Number) + 1 for some IdKind. Everything was in one stored procedure in one transaction so value of Number was unique for IdKind.
How to accomplish the same in Entity Framework. Value of Number should be computed when creating new object or when changing IdKind.
I had the same problem but I solved it in c#.
I should have an entity mapped to the table:
I should have and auxiliary entity to store the last number used per Kind.
Then before adding a row (MyEntity object) to the table, I should calculate the proper Number using the LastNumber field of the LastNumberEntity with Kind equals to my Kind value.
We must note that this strategy has a concurrency problem because two different threads could be adding an object of the same Kind at the same time, those threads will inspect the same LastNumberEntity to get the LastNumber value. This problem has a known solution in entityframework. The code could looks like this:
This method gets an incremental number for a specified Kind and handles the concurrency problem, using it, we can set the Number value for each MyEntity object. The client code could looks like this:
This code could be refactored, making the setters private, making a factory to ensure the entities always are created using the GetNumber method and using repositories to manage the db.
I would use database trigger for that and configure
Number
property in EF mapping withStoreGeneratedPattern.Computed
to inform EF that this property is filled in the database and must be reloaded after each update / insert.I would also not use max() for each new number. Instead I would maintain separate table simulating sequences. This table should contain record per sequence - in your case record per
IdKind
with current max number. Instead of selecting aggregation you will select single record and update it to contain new max number. Working with this table must be in the same transaction as persisting changes to your entity.