Как избежать дублирования вставки в Entity Framework 4.3.1

У меня есть небольшая модель, созданная с использованием подхода code-first — класс City, который содержит только информацию о названии города.

public class City
{
    public City()
    {
        Posts = new List<Post>();
    }

    public City(string cityName)
    {
        Name = cityName;
    }

    public virtual ICollection<Post> Posts { get; private set; }
    public int Id { get; set; }
    public string Name { get; private set; }
}

Класс Post представляет собой комбинацию почтового индекса и ссылки на город.

public class Post
{
    public virtual City City { get; set; }        
    public int Id { get; set; }
    public string ZipCode { get; set; }        
}

обе сущности имеют свои наборы, определенные в контексте как их конфигурации

public DbSet<City> Cities { get; set; }
public DbSet<Post> Posts { get; set; }

modelBuilder.Configurations.Add(new CityMap());
modelBuilder.Configurations.Add(new PostMap());


public class CityMap : EntityTypeConfiguration<City>
{
    public CityMap()
    {
        // Primary Key
        HasKey(t => t.Id);

        // Properties
        // Table & Column Mappings
        ToTable("City");
        Property(t => t.Id).HasColumnName("Id");
        Property(t => t.Name).HasColumnName("Name");
    }
}

public class PostMap : EntityTypeConfiguration<Post>
{
    public PostMap()
    {
        // Primary Key
        HasKey(t => t.Id);

        // Properties
        // Table & Column Mappings
        ToTable("Post");
        Property(t => t.Id).HasColumnName("Id");            
        Property(t => t.ZipCode).HasColumnName("ZipCode");

        // Relationships
        HasRequired(t => t.City)
        .WithMany(t => t.Posts)
        .Map(map=>map.MapKey("CityId"));
    }
}

Я создал класс для манипулирования этими объектами со статическими методами, которые получают или создают объекты и возвращают их вызывающей стороне.

private static City GetCity(string cityName)
{
        City city;

        using (var db = new DbContext())
        {
            city = db.Cities.SingleOrDefault(c => c.Name == cityName);

            if (city == null)
            {
                city = new City(cityName);
                db.Cities.Add(city);
                db.SaveChanges();                    
            }
        }

        return city;
    }

    private static Post GetPost(string zipCode, string cityName)
    {
        Post post;

        City city = GetCity(cityName);

        using (var db = new DbContext())
        {      
            post = db.Posts.SingleOrDefault(p => p.City.Id == city.Id && p.ZipCode == zipCode);
            if (post == null)
            {
                post = new Post { City = city, ZipCode = zipCode };

                // State of city is unchanged
                db.Posts.Add(post);

                // State of city is Added
                db.SaveChanges();
            }
        }

        return post;
    }

Представьте, что я вызываю метод

GetPost("11000","Prague");

запускается метод GetCity, и если он не существует, метод создает city, а затем вызывает метод SaveChanges().

Если я установлю возвращенный объект city в новый экземпляр Post, Entity Framework создаст вторую вставку для того же city.

Как избежать такого поведения? Я хочу вставить только новый объект post со ссылкой на city, созданный или загруженный на предыдущем шаге.


person Rudolf Dvoracek    schedule 08.11.2012    source источник


Ответы (1)


Вам нужно установить State вашего города, когда вы прикрепите его к неизменному

context.Entry(city).State = EntityState.Unchanged;
person podiluska    schedule 08.11.2012
comment
Спасибо, podiluska, я попробовал тот же подход в своем коде, нет ли альтернативного способа? - person Rudolf Dvoracek; 08.11.2012
comment
Спасите горе и используйте этот внешний ключ. Почему Entity Framework повторно вставляет существующие объекты в мою базу данных? msdn.microsoft.com/en-us/magazine/dn166926.aspx - person Colin; 12.05.2014