3

My Domain Classes:

public class Address
{
    [Key]
    public virtual string AddressId { get; set; }

    public virtual Site Site { get; set; }
}

public class Site
{
    [Key]
    public virtual int SiteId { get; set; }

    public virtual Address Address { get; set; }
}

Mapping using Fluent API:

public class SiteMappings : EntityTypeConfiguration<Site>
{
    public SiteMappings()
    {
        HasRequired(s => s.Address)
        .WithOptional(a => a.Site)
        .Map(s => s.MapKey("AddressId"))
        .WillCascadeOnDelete(false);
    }
}

Seed Method:

var addresses = new List<Address>
{
    new Address { AddressId = "1" }
};
addresses.ForEach(s => context.Addresses.AddOrUpdate(p => p.AddressId, s));

var sites = new List<Site>
{
    new Site { SiteId = 1, Address = addresses.Single(s => s.AddressId.Equals("1"))}
};
sites.ForEach(s => context.Sites.AddOrUpdate(p => p.SiteId, s));

Error:

Violation of PRIMARY KEY constraint 'PK_dbo.Addresses'. Cannot insert duplicate key in object 'dbo.Addresses'. The duplicate key value is (1)

It seems to be when I try to add a new "site", new "address" also get inserted. How to avoid this? How to insert an existing "address" in DBcontext I just added before. I'm new to Entity Framework and really appreciate your help. Thanks in advance!

guitarlass
  • 1,587
  • 7
  • 21
  • 45
Para Kan
  • 121
  • 3
  • 12
  • Hello, I ran into a similar problem. I have similar classes and I'm trying to save a Model1 with a selected option from a drop down of Model2s. my error is "Entities in 'Mydbcontext' participate in the 'model1_model2' relationship. 0 related 'model1_model2_Target' were found. 1 'model1_model2_Target' is expected" its a 1 to 1 relationship. – guitarlass Jul 28 '14 at 04:45
  • 1
    I was able to solve this issue by inserting an "Address" managed by the current context. `new Site { SiteId = 1, Address = context.Addresses.FirstOrDefault(a => a.AddressId.Equals("1"))}` – Para Kan Jul 28 '14 at 05:12

2 Answers2

2

After you assign the address to the site instance, use this for each address instance:

context.Entry(existingAddress).State = EntityState.Unchanged;

This will set the state of the addresses as Unchanged instead of Added and EF will not try to add them a second time.

Also try calling context.SaveChanges() after the ForEach where you add the addresses.

Liviu Mandras
  • 6,540
  • 2
  • 41
  • 65
  • `Attaching an entity of type 'TransportManagementSystem.Models.Address' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.` – Para Kan Jul 28 '14 at 05:10
  • See my edit above. And btw, why is your `AddressId` a string and not an `int` since you assign it a value of 1? Is it a mistake or by design? – Liviu Mandras Jul 28 '14 at 05:13
  • I tried `addresses.ForEach(s => context.Addresses.AddOrUpdate(p => p.AddressId, s));` `context.SaveChanges();` `var sites = new List { new Site { SiteId = 1, Address = addresses.Single(s => s.AddressId.Equals("1"))} };` `sites.ForEach(s => context.Sites.AddOrUpdate(p => p.SiteId, s));` `context.Entry(addresses.Single(s => s.AddressId.Equals("1"))).State = EntityState.Unchanged;` `context.SaveChanges();` Error: **more than one entity of type 'TransportManagementSystem.Models.Address' have the same primary key value** – Para Kan Jul 28 '14 at 06:05
1

I was able to solve this issue by inserting an "Address" managed by the current context.

new Site { SiteId = 1, Address = context.Addresses.FirstOrDefault(a => a.AddressId.Equals("1"))}

Below code will utilize an existing "Address" managed by the current context instead of trying to insert a new "Address".

context.Addresses.FirstOrDefault(a => a.AddressId.Equals("1"))}
Para Kan
  • 121
  • 3
  • 12