1

わかりました、これはおそらく私が間違っている概念ですが、とにかく... (MVC3) リスト プロパティを持つエンティティがあります。私の CRUD ビューは、Ajax ポストを介して JSON 表現をコントローラーに送信します。そのエンティティの更新を投稿しているときにリスト プロパティがまったく更新されないことを除いて、すべてがうまく機能しています。エンティティのすべての単純なプロパティが更新されますが、(私が想像するように) 更新ツリーには List プロパティが含まれていません。リスト上のこれらの変更を EF に認識させるにはどうすればよいですか?

これまでのコードの一部を次に示します。

    [HttpPost]
    public JsonResult Edit(Lote lote)
    {
            //Given the IDs present in lote.Documentos, load the List of Documentos
            if (lote.Documentos != null)
            {
                List<Documento> ldoc = new List<Documento>();
                foreach (var d in lote.Documentos)
                {
                    ldoc.Add(db.Documentos.Find(d.IDDocumento));
                }
                lote.Documentos.Clear();
                foreach (var d in ldoc)
                {
                    lote.Documentos.Add(d);
                }
            }

            //Now, clear all the previous errors
            foreach (var modelValue in ModelState.Values)
            {
                modelValue.Errors.Clear();
            }
            //And re-validate the model
            ValidateModel(lote);

            if (ModelState.IsValid)
            {
                if (lote.IDLote > 0)
                {
                    //Updating
                    db.Entry(lote).State = EntityState.Modified;
                }
                else
                {
                    //Inserting
                    db.Lotes.Add(lote);
                }
                db.SaveChanges();
                CustomMessages.Sucesso(TempData, "Informações salvas com sucesso.", 10000);
                return Json(new { Success = 1, IDProprietario = lote.IDLote, ex = "" });
            }
            else
            {
                return Json(new { Success = 0, ex = "Falha na rotina de armazenamento das informações"});
            }

そして、それらはクラス自体です:

public class Lote
{
    [Key]
    public int IDLote { get; set; }

    (... lots of properties ...)

    [Display(Name = "Documentos")]
    public List<Documento> Documentos { get; set; }
}


public class Documento
{
    //---=== ATRIBUTOS ===---
    [Key]
    public int IDDocumento { get; set; }

    [Required]
    [MaxLength(60)]
    public string Nome { get; set; }

    public List<Lote> Lotes { get; set; }
}

これは多対多の関係であるため、これも取得しました。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove
        <System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();

        modelBuilder.Entity<Lote>()
            .HasMany(t => t.Documentos)
            .WithMany(t => t.Lotes)
            .Map(m =>
            {
                m.ToTable("LoteDocumento");
                m.MapLeftKey("IDLote");
                m.MapRightKey("IDDocumento");
            });
(... and some other stuff)

これについて何か助けはありますか?

4

1 に答える 1

0

この行を変更してみてください:

ldoc.Add(db.Documentos.Find(d.IDDocumento));

ldoc.Add(db.Documentos.Include("Lotes").FirstOrDefault(x => x.IDDocumento == d.IDDocumento));

変更するリレーションシップ/オブジェクトが実際に現在のDBコンテキストにアタッチされていることを確認する必要があります。そうしないと、エンティティフレームワークはそれらに加えられた変更を追跡できません。

このリンクはオブジェクトコンテキストの観点から説明していますが、同じルールがDBcontextにも当てはまると思います。

それでもうまくいかない場合は、EFの仕組みをよりよく理解しようとしている原因を教えてください。

さて、役立ついくつかのリンクを見つけました:

同じキーを持つオブジェクトは、ObjectStateManagerにすでに存在します。ObjectStateManagerは、同じキーを持つ複数のオブジェクトを追跡できません

エンティティフレームワークと接続プール

実行するInclude("Lotes")と、Documentosに関連するロットがDBContextに追加されます。エンティティフレームワークは現在、これらのオブジェクトを追跡しています。コードのさらに下の方で、この行を使用してコンテキストにそれらを再追加していますdb.Entry(lote).State = EntityState.Modified;。とにかくそれは私の推測です。

上記のリンクに基づいて、私はあなたがこのように持っているものを書き直そうとします(コンパイルされていません):

[HttpPost]
public JsonResult Edit(Lote lote)
{
    //get old Lote from DB
    var oldLote = db.Lotes.include("Documentos").FirstOrDefault(x => x.IDLote == lote.IDLote);

    //update
    if(oldLote != null)
    {
        //refresh any other properties that you may have changed on it.
        db.Entry(oldLote).CurrentValues.SetValues(lote);

        //not sure if you will even need this section any more but then you can...
        oldLote.Documentos.Clear();
        foreach (var d in lote.Documentos)
        {
            oldLote.Documentos.Add(db.Documentos.include("Lotes").FirstOrDefault(x => x.IDDocumento == d.IDDocumento));
        }
    }    
    else //add
    {
        //not sure if this will work
        foreach (var d in lote.Documentos)
        {
            db.Entry(d).State = EntityState.Modified;
        }

        db.Lotes.Add(lote);
    }

    //then just save changes.  EF is already tracking all your objects and changes.
    db.SaveChanges();
....
于 2012-12-14T18:32:00.897 に答える