I have two tables:
CREATE TABLE [dbo].[Customers] (
[CustomerId] INT IDENTITY (1, 1) NOT NULL,
CONSTRAINT [PK_dbo.Customers] PRIMARY KEY CLUSTERED ([CustomerId] ASC)
);
CREATE TABLE [dbo].[Campaigns] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[CustomerId] INT NULL,
[CampaignId] INT NULL,
CONSTRAINT [PK_dbo.Campaigns] PRIMARY KEY CLUSTERED ([Id] ASC)
);
Campaigns.CampaignId is unique to every CustomerId; therefore, it cannot be an identity. So from my web app, I need to auto increment the CampaignId upon Campaign creation. In the past, I've had to obtain a lock in a single transaction to obtain the next highest and issue an insert. How would I accomplish the same thing in EF without having to worry about or effectively manage concurrency?
In the Campaign controller, I have this (UserContext is a static helper class that retrieves the user's current CustomerId and db is my DbContext):
public ActionResult Create(Campaign campaign)
{
if (ModelState.IsValid)
{
int customerId = UserContext.customerId;
int maxCampaignId = db.Campaigns.Where(c => c.CustomerId == customerId).Max(c => c.CampaignId);
campaign.CampaignId = maxCampaignId + 1;
db.Campaigns.Add(campaign);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(campaign);
}
But wouldn't this risk duplicate values per CustomerId in a high concurrency environment?
EDIT:
I forgot to mention that a guid was not an option. The Ids have to be integers.
EDIT 2:
I forgot to mention that there is also a Users table which can have the same CustomerId. Users can create multiple Campaigns with the same CustomerId which causes the potential for concurrency issues.