Reputation: 1471
This is the classical "upsert" problem. I know how to achieve this using pure SQL, but wasn't able to find the equivalent using Entity Framework (v6, code first).
Given the following entity:
public class Product
{
[Key]
public int Id { get; set; }
public string Sku { get; set; } // Should be unique
// Other properties
}
I want to create the Save(Product p) method which creates new record if the given Sku does not exist, or updates the existing record if that Sku already exist in the database. The Save method must not create records with duplicate Skus. Also, no unique constraints are defined on the Sku column in the DB.
Checking for duplicates before inserting the record obviously won't work in multi-process environment. I tried wrapping the check in a transaction but that didn't work:
using (var db = new MyDbContext())
using (var transaction = db.Database.BeginTransaction())
{
// if exists, retrieve and update
// otherwise insert
db.SaveChanges();
transaction.Commit();
}
Any clever ideas?
Thanks!
Upvotes: 3
Views: 3732
Reputation: 2009
If you use Entity Framework 6.1+, Index
annotation's IsUnique
property can be used.
In question, you mention insert without unique constraint
, however, in this uniqueness
is achieved via code first. I hope this is your want.
public class Product
{
[Key]
public int Id { get; set; }
[StringLength(450)]
[Index(IsUnique = true)]
public string Sku { get; set; }
// Other properties
}
When I run this code, SaveChanges
throws DbUpdateExceptions
as expected.
using (DataContext dataContext = new DataContext())
{
MyClass myClass1 = new MyClass() {Sku = "test1"};
MyClass myClass2 = new MyClass() {Sku = "test2"};
MyClass myClass3 = new MyClass() {Sku = "test2"};
MyClass myClass4 = new MyClass() {Sku = "test3"};
dataContext.TestTable.Add(myClass1);
dataContext.TestTable.Add(myClass2);
dataContext.TestTable.Add(myClass3);
dataContext.TestTable.Add(myClass4);
dataContext.SaveChanges();
}
Upvotes: 2