2015-09-17 6 views
0

я следующие лица:сохраняющиеся Entity Framework гнездились/связанные объекты

public class ModuleCriteria 
{ 
    public int ModuleCriteriaId { get; set; } 

    public string Criteria { get; set; } 

    public List<ModuleCriteriaLookup> ModuleCriteriaLookups { get; set; 
} 
} 

public class ModuleCriteriaLookup 
{ 
    public int ModuleCriteriaLookupId { get; set; } 

    public int ModuleCriteriaId { get; set; } // ** (Foreign Key) ** 

    public int SiteId { get; set; } 

    public string CategoryId { get; set; } 

    public ModuleCriteria ModuleCriteria { get; set; } 
} 

У меня есть следующие конфигурации EF в моем Context классе (под редакцией для краткости):

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 

    modelBuilder.Entity<ModuleCriteriaLookup>().HasRequired(mc => mc.ModuleCriteria); 

    // I tried adding the below line but it made no difference. 
    //modelBuilder.Entity<ModuleCriteria>().HasMany(mc => mc.ModuleCriteriaLookups); 
} 

... и Я следующие DbSet свойства, определенные в моем Context классе:

public DbSet<ModuleCriteria> ModuleCriteria { get; set; } 

public DbSet<ModuleCriteriaLookup> ModuleCriteriaLookup { get; set; } 

У меня есть CriteriaRepository класса, у которого есть метод Save, для сохраняющихся изменений для моих ModuleCriteria лиц:

public void Save(ModuleCriteria moduleCriteria) 
{ 
    using (var ctx = new MyAppContext()) 
    { 
     ctx.Entry(moduleCriteria).State = moduleCriteria.ModuleCriteriaId == 0 ? EntityState.Added : EntityState.Modified; 

     ctx.SaveChanges(); 
    } 
} 

ModuleCriteria объекта может существовать без ModuleCriteriaLookup объекта, но ModuleCriteriaLookup объекта должен относиться к существующим ModuleCriteria объекту (связанные с ModuleCriteriaId).

У вас может быть несколько ModuleCriteraLookup объектов, относящихся к одному и тому же объекту ModuleCriteria.

Поведение, которое я хотел бы, и ожидать, что с EF, является:

1) Если я создаю новый ModuleCriteria объект (без каких-либо ModuleCriteriaLookups), вызовите метод Save в моем хранилище, я бы ожидал увидеть новый ModuleCriteria запись в db без связанных ModuleCriteriaLookup записей в дБ.

2) Если я создаю новый объект ModuleCriteria и назначить List<ModuleCriteriaLookup> к нему, вызовите метод Save в моем хранилище, я бы ожидать, чтобы увидеть новый ModuleCriteria запись в БД и х новых ModuleCriteriaLookup строк в БД, которые относятся к что конкретно ModuleCriteria.

3) Если добавить/редактировать/удалить любого из ModuleCriteriaLookup объектов, относящихся к одному из моих ModuleCriteria объектов, а затем вызвать метод Save в моем хранилище, я бы ожидать, чтобы увидеть какие-либо из ModuleCriteria-х удалены ModuleCriteriaLookup объектов для удаления из db, любые новые добавленные и любые отредактированные просто для обновления.

Так все, что я когда-либо нужно беспокоиться о том, что независимо от ModuleCriteria.ModuleCriteriaLookups свойство содержит для данного ModuleCriteria, это то, что будет отражено в 2 таблицы в моей БД, просто вызвав метод Save для ModuleCriteria объекта в моем хранилище.

К сожалению, на данный момент, если я добавляю новый объект ModuleCriteria с соответствующей List<ModuleCriteriaLookup> добавляет оба ModuleCriteria и х ModuleCriteriaLookup строк в БД красиво. Но когда я хочу редактировать или удалять записи в свойстве ModuleCriteria.ModuleCriteriaLookups, это не отражается в db. Ничего не происходит с рядами ModuleCriteriaLookups.

Я не уверен, где именно проблема, будь то конфигурация отображения EF или что-то делать с тем, как работает репозиторий?

+0

@Irshad пожалуйста смотреть его с предлагаемыми редактирования подряд, который добавляет 'инлайн code' к столбам. Это не всегда делает его более читаемым. – CodeCaster

+0

Где во время конфигурации модели вы указываете, что ModuleCriteriaId является FK для ModuleCriteria? Я не видел этого в методе OnModelCreating. Возможно, стоит добавить в 'modelBuilder.Entity (). HasRequired (mc => mc.ModuleCriteria) .WithMany (m => m.ModuleCriteriaLookup) .HasForeignKey (mc => mc.ModuleCriteriaId) .WillCascadeOnDelete (true) ' – DDiVita

+0

@CodeCaster К сожалению, я не понял. – Irshad

ответ

1

Проблема находится в репозитории. DbContext должен знать о существовании сущностей. Поэтому при редактировании и/или удалении объектов сначала необходимо получить объекты из базы данных.

Это description ясно сказано:

Свойство .Entry возвращает объекты из контекста, которые будучи отслеживаются контекстом.

Поскольку вы непосредственно используете эти свойства сразу после создания контекста, контекст не отслеживает эти объекты и поэтому не знает, что что-то изменилось. И, следовательно, он не может генерировать правильные операторы SQL.

Существует несколько способов борьбы с этим, в зависимости от остальной части вашего дизайна.

Один из способов удалить это будет:

public void DeleteModuleCriteriaLookup(ModuleCriteriaLookup[] lookups) 
    { 
     using (var ctx = new MyAppContext()) 
     { 
      var moduleCriteriaId = lookups.First().ModuleCriteriaId; 

      var moduleCritria = (
       from criteria in ctx.ModuleCriteria 
       where criteria.ModuleCriteriaId == moduleCriteriaId 
       select criteria 
       ).Single(); 

      var lookupIdsToDelete = lookups.Select(l => l.ModuleCriteriaLookupId); 

      var lookupsToDelete = (
       from lookup in moduleCritria.ModuleCriteriaLookups 
       where lookupIdsToDelete.Contains(lookup.ModuleCriteriaLookupId) 
       select lookup 
       ).ToArray(); 

      foreach (var lookup in lookupsToDelete) 
      { 
       moduleCritria.ModuleCriteriaLookups.Remove(lookup); 
      } 

      ctx.SaveChanges(); 
     } 
    } 
Смежные вопросы