2015-01-23 5 views
0

Я пытаюсь обновить объекты в Entity Framework, и я хотел бы знать, какой лучший способ обновления Entities, которые содержат список других объектов.Обновление объекта в Entity Framework, который содержит списки других объектов

Рассмотрим следующий пример:

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace EntityFrameworkUpdateSketch 
{ 
public class A 
{ 
    [Key] 
     [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)] 
    public int Akey {get;set;} 

    public string Aname { get; set; } 

    public virtual List<B> Blist {get;set;} 

    public A() 
    { 
     Blist = new List<B>(); 
    } 
} 

public class B 
{ 
    public virtual A owner { get; set; } 

    [ForeignKey("owner")] 
    [Key, Column(Order = 0)] 
    public int Akey { get; set; } 

    [Key, Column(Order = 1)] 
    public int Order { get; set; } 


    public string Bname { get; set; } 
} 

public class Database: DbContext 
{ 
    public DbSet<A> As { get; set; } 
    public DbSet<B> Bs { get; set; } 
} 

public class Program 
{   
    static void Main(string[] args) 
    { 
     // Make a new object 

     using (Database db = new Database()) 
     { 
      A intodb = new A(); 

      intodb.Akey = 1;     

      intodb.Aname = "Name of A object"; 

      intodb.Blist.Add(new B() { Bname = "Name of B object one",Order=1 }); 

      intodb.Blist.Add(new B() { Bname = "Name of B object two",Order=2 }); 

      db.As.Add(intodb); 

      db.SaveChanges(); 
     } 

     // Update the object in database 

     using (Database db = new Database()) 
     {      
      // Imagine I got "update" from somewhere else 

      A update = new A(); 

      update.Akey = 1; 

      update.Aname = "New Name of A object"; 

      update.Blist.Add(new B() { Bname = "New Name of B object one" ,Akey=1, Order=1}); 

      update.Blist.Add(new B() { Bname = "New Name of B object two", Akey = 1, Order = 2 }); 

      update.Blist.Add(new B() { Bname = "A whole new object 3", Akey = 1, Order = 3 }); 


      db.Entry<A>(update).State = EntityState.Modified;     

      db.SaveChanges(); 
     } 
    } 
} 
} 

У меня есть объект «А», который содержит список в качестве свойства.

В первой половине моей демонстрационной программы я создаю новый объект типа A, а затем сохраняю его в базе данных.

Во втором полугодии я создаю новый объект под названием A, и я хочу обновить объект в базе данных новыми значениями - я хочу изменить имена B, и я хочу добавить новый B-объект в список.

Это работает для изменения A, но подкатегории B не работают - у них нет новых имен.

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

Я не могу удалить A и повторно добавить его (хотя это работает), потому что это нарушает внешние ключи. У меня есть каскадные удаления в моем «реальном» решении, которое удаляет ссылки в другом месте, если я удалю свой объект A.

Вам не нужно ничего знать о WebAPI или PUT, чтобы ответить на этот вопрос.

+0

Какое сообщение об ошибке вы получаете и какую версию Entity Framework используете? –

+0

Во второй части вы присоединяете 'A' к контексту. EF никогда не знает о новых 'B's. 'db.Entry <>(). State' влияет только на скалярные свойства, никаких свойств навигации. –

+0

@ Ник Я использую EF 6.1. Нет никаких сообщений об ошибках, просто база данных не обновляется, как хотелось бы – Skippy

ответ

0

Вот программа, которая работает, но может быть улучшена. Вся эта программа теперь удаляет все объекты B в базе данных, которые принадлежат A, а затем повторно добавляет. Это работает, но кажется плохим. Любые улучшения?

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace EntityFrameworkUpdateSketch 
{ 
public class A 
{ 
    [Key] 
    [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)] 
    public int Akey {get;set;} 

    public string Aname { get; set; } 

    public virtual List<B> Blist {get;set;} 

    public A() 
    { 
     Blist = new List<B>(); 
    } 
} 

public class B 
{ 
    public virtual A owner { get; set; } 

    [ForeignKey("owner")] 
    [Key, Column(Order = 0)] 
    public int Akey { get; set; } 

    [Key, Column(Order = 1)] 
    public int Order { get; set; } 


    public string Bname { get; set; } 
} 

public class Database: DbContext 
{ 
    public DbSet<A> As { get; set; } 
    public DbSet<B> Bs { get; set; } 
} 

public class Program 
{   
    static void Main(string[] args) 
    { 
     // Make a new object    
     using (Database db = new Database()) 
     { 
      A intodb = new A(); 

      intodb.Akey = 1;     

      intodb.Aname = "Name of A object"; 

      intodb.Blist.Add(new B() { Bname = "Name of B object one",Order=1 }); 

      intodb.Blist.Add(new B() { Bname = "Name of B object two",Order=2 }); 

      db.As.Add(intodb); 

      db.SaveChanges(); 
     } 

     // Update the object in database 

     using (Database db = new Database()) 
     {      
      // Imagine I got "update" from somewhere else 

      A update = new A(); 

      update.Akey = 1; 

      update.Aname = "New Name of A object"; 

      update.Blist.Add(new B() { Bname = "New Name of B object one" ,Akey=1, Order=1}); 

      update.Blist.Add(new B() { Bname = "New Name of B object two", Akey = 1, Order = 2 }); 

      update.Blist.Add(new B() { Bname = "A whole new object 3", Akey = 1, Order = 3 }); 


      db.Entry<A>(update).State = EntityState.Modified;     

      // Clear all existing B objects attached to the updated object 

      var query = from c in db.Bs.AsEnumerable() where c.Akey==update.Akey select c; 

      foreach (var z in query) 
      { 
       db.Bs.Remove(z); 
      } 

      // Readd B objects 

      foreach (var i in update.Blist) 
      { 
       db.Bs.Add(i); 
      } 

      db.SaveChanges();        
     } 
    } 

} 
} 
Смежные вопросы