We have always enjoyed the use of a sequence in Oracle databases in order to create globally-unique primary key IDs across an entire database. So much, that we will mimic the same thing when using SQL Server databases:
CREATE TABLE MainSequence(
Id int IDENTITY(1,1) CONSTRAINT pkMainSequence PRIMARY KEY
)
I'm trying to switch over to Entity Framework, which is very new to me. It seemed like it would be trivial to create an extension method that I could use to quickly get the next available globally-unique Id.
public static int GetNextId( this Entities db ) {
var ms = new MainSequence();
db.MainSequences.AddObject( ms );
db.SaveChanges( SaveOptions.None );
return ms.Id;
}
Since it's an identity column, all I should have to do is add a new object to the database and save the changes so that the Id property is updated with a real value. This works fine. But I seem to run into trouble when trying to use it for foreign-key-related tables:
var dataId = db.GetNextId();
db.Datas.AddObject( Data.CreateData( dataId, someValueForThisColumn );
db.Caches.AddObject(
Cache.CreateCache( db.GetNextId(),
DatabaseMethods.GetOrAddLocation( source.GetLocationText() ),
DateTime.Now,
dataId ) );
The Cache table has a foreign key to the Data table. When SaveChanges(); is called immediately after this, an exception is generated.
System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'pkData'. Cannot insert duplicate key in object 'dbo.Data'. The duplicate key value is (78162). The statement has been terminated.
For some reason it appears the new data row is trying to get inserted into the database twice, though I'm not sure why that would be. I've confirmed that for every time the code is run, a different MainSequence ID is returned. It seems as though calling db.SaveChanges whenever a new ID is obtained is the problem, but there's no other way that can get populated with a real int and I don't see why it would be a problem. What am I doing wrong?
SEQUENCEdb object), or then use theIDENTITYcolumn specifier to let SQL Server automatically dish out sequential ID's for your table - don't replicate this manually, that's a disaster waiting to happen....SaveChanges(SaveOption)method where either I'm not allowed to call it several times, or need to do it in some other way.dataId(var dataId = 12345)