I am using Entity Framework 6 DB First with SQL Server tables that each have a uniqueidentifier
primary key. The tables have a default on the primary key column that sets it to newid()
. I have accordingly updated my .edmx to set the StoreGeneratedPattern
for these columns to Identity
. So I can create new records, add them to my database context and the IDs are generated automatically. But now I need to save a new record with a specific ID. I've read this article which says you have to execute SET IDENTITY_INSERT dbo.[TableName] ON
before saving when using an int identity PK column. Since mine are Guid and not actually an identity column, that's essentially already done. Yet even though in my C# I set the ID to the correct Guid, that value is not even passed as a parameter to the generated SQL insert and a new ID is generated by the SQL Server for the primary key.
I need to be able to both :
- insert a new record and let the ID be automatically created for it,
- insert a new record with a specified ID.
I have # 1. How can I insert a new record with a specific primary key?
Edit:
Save code excerpt (Note accountMemberSpec.ID is the specific Guid value I want to be the AccountMember's primary key):
IDbContextScopeFactory dbContextFactory = new DbContextScopeFactory();
using (var dbContextScope = dbContextFactory.Create())
{
//Save the Account
dbAccountMember = CRMEntity<AccountMember>.GetOrCreate(accountMemberSpec.ID);
dbAccountMember.fk_AccountID = accountMemberSpec.AccountID;
dbAccountMember.fk_PersonID = accountMemberSpec.PersonID;
dbContextScope.SaveChanges();
}
--
public class CRMEntity<T> where T : CrmEntityBase, IGuid
{
public static T GetOrCreate(Guid id)
{
T entity;
CRMEntityAccess<T> entities = new CRMEntityAccess<T>();
//Get or create the address
entity = (id == Guid.Empty) ? null : entities.GetSingle(id, null);
if (entity == null)
{
entity = Activator.CreateInstance<T>();
entity.ID = id;
entity = new CRMEntityAccess<T>().AddNew(entity);
}
return entity;
}
}
--
public class CRMEntityAccess<T> where T : class, ICrmEntity, IGuid
{
public virtual T AddNew(T newEntity)
{
return DBContext.Set<T>().Add(newEntity);
}
}
And here is the logged, generated SQL for this:
DECLARE @generated_keys table([pk_AccountMemberID] uniqueidentifier)
INSERT[dbo].[AccountMembers]
([fk_PersonID], [fk_AccountID], [fk_FacilityID])
OUTPUT inserted.[pk_AccountMemberID] INTO @generated_keys
VALUES(@0, @1, @2)
SELECT t.[pk_AccountMemberID], t.[CreatedDate], t.[LastModifiedDate]
FROM @generated_keys AS g JOIN [dbo].[AccountMembers] AS t ON g.[pk_AccountMemberID] = t.[pk_AccountMemberID]
WHERE @@ROWCOUNT > 0
-- @0: '731e680c-1fd6-42d7-9fb3-ff5d36ab80d0' (Type = Guid)
-- @1: 'f6626a39-5de0-48e2-a82a-3cc31c59d4b9' (Type = Guid)
-- @2: '127527c0-42a6-40ee-aebd-88355f7ffa05' (Type = Guid)