When I try to save my entity, I get the following exception:
"AcceptChanges cannot continue because the object key values conflict with another object in the ObjectStateManager. Before invoking AcceptChanges, make sure the key values are unique."
I am creating a three-tier application where the data access layer uses EF Code First and where the client calls the middle layer using WCF. Therefore, I cannot allow the context to track the state of the object when creating the object on the client.
In some situations, I find that the same object is contained twice in the object graph. In this situation, it fails when I try to set the state of the duplicate entity.
For example, I have the following objects: Client Country Curreny
- From the client, I create a new client instance. Then I make a service call to get the country instance and assign it to the customer. A copy of the country currency associated with it.
- The user can then associate Currency with the customer. They can choose the same currency that are associated with the country.
- I am making another service call to get this. Thus, at this stage we can have two separate copies of the same currency.
So, in the end, I get two instances of the same object in the object graph.
When saving an object (in my service) I need to tell EF that both Currency objects are not changed (if I do not do this, I get duplicates). The problem is that I got the exception above.
When saving, if I set the Currency instance on the Country instance to null, it solves the problem, but I feel the code is getting more dirty (because of this and other WCF EF-related workarounds that I need to implement).
Are there any suggestions on how to resolve this better?
Thanks so much for any help in advance. Here is the code:
using System; using System.Collections.Generic; using System.Data.Entity.ModelConfiguration; using System.ComponentModel.DataAnnotations; using System.Data.Entity; using System.Linq; namespace OneToManyWithDefault { public class Customer { public int Id { get; set; } public string Name { get; set; } public Country Country { get; set; } public Currency Currency { get; set; } public byte[] TimeStamp { get; set; } } public class Country { public int Id { get; set; } public string Name { get; set; } public Currency Currency { get; set; } public byte[] TimeStamp { get; set; } } public class Currency { public int Id { get; set; } public string Symbol { get; set; } public byte[] TimeStamp { get; set; } } public class MyContext : DbContext { public DbSet<Customer> Customers { get; set; } public DbSet<Currency> Currency { get; set; } public DbSet<Country> Country { get; set; } public MyContext(string connectionString) : base(connectionString) { Configuration.LazyLoadingEnabled = false; Configuration.ProxyCreationEnabled = false; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new CustomerConfiguration()); modelBuilder.Configurations.Add(new CountryConfiguration()); modelBuilder.Configurations.Add(new CurrencyConfiguration()); base.OnModelCreating(modelBuilder); } } public class CustomerConfiguration : EntityTypeConfiguration<Customer> { public CustomerConfiguration() : base() { HasKey(p => p.Id); Property(p => p.Id) .HasColumnName("Id") .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) .IsRequired(); Property(p => p.TimeStamp) .HasColumnName("TimeStamp") .IsRowVersion(); ToTable("Customers"); } } public class CountryConfiguration : EntityTypeConfiguration<Country> { public CountryConfiguration() : base() { HasKey(p => p.Id); Property(p => p.Id) .HasColumnName("Id") .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) .IsRequired(); Property(p => p.TimeStamp) .HasColumnName("TimeStamp") .IsRowVersion(); ToTable("Countries"); } } public class CurrencyConfiguration : EntityTypeConfiguration<Currency> { public CurrencyConfiguration() : base() { HasKey(p => p.Id); Property(p => p.Id) .HasColumnName("Id") .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) .IsRequired(); Property(p => p.TimeStamp) .HasColumnName("TimeStamp") .IsRowVersion(); ToTable("Currencies"); } } class Program { private const string ConnectionString = @"Server=.\sql2005;Database=DuplicateEntities;integrated security=SSPI;"; static void Main(string[] args) {