2

ユーザーが新しいビューに移動せずにコレクションにアイテムを追加できるビューを作成しようとしています(シナリオは、ユーザーが仕事の経験やスキルなどに関する情報を追加する一種のCVサイトです。新しいビューに移動してそれぞれの小さなものを追加するのはばかげているようです)。

そのため、すでに追加されたアイテムのテキストボックスの数を表示する編集ビューがあり、ユーザーがアイテムを追加した場合にコレクションを新しくフェッチするメソッドに移動するajax呼び出しがあります。

問題のメソッドは次のとおりです。

    public ActionResult Edit(int id)
    {
        Consultant consultant = _repository.GetConsultant(id);
        var vm = GetViewModel(consultant);
        return View(vm);
    }

    private DetailsViewModel GetViewModel(Consultant consultant)
    {
        return new DetailsViewModel
        {
            Programs = consultant.Programs.ToList(),
            Consultant = consultant
        };
    }
    public ActionResult NewProgram(int id)
    {
        //TODO: ordering is rather strange, because the entitycollection adds at the beginning rather than the end...
        Consultant consultant = _repository.GetConsultant(id);
        consultant.Programs.Add(new Program()); 
        _repository.Save();
        var vm = GetViewModel(consultant);
        return PartialView("ProgramList", vm);
    }

ここで質問になります。NewProgramメソッドが呼び出されると、Consultantオブジェクトに新しいプログラムが追加され、返送する新しいViewModelが作成されますが、新しいプログラムはEntityCollectionの最後ではなく最初に追加されます。ただし、フォーム全体を投稿し、編集ビューを再度開くと、リストは新しく追加されたプログラムを最後に配置します。これは非常に奇妙です。ユーザーはリストの最初にアイテムを追加したと思いますが、ページに戻ると、最後に新しいアイテムが見つかります。

なぜこれを行うのですか?NewProgram()に新しいプログラムを最後に直接追加させる方法はありますか?

そして、EFオブジェクトを直接操作するのではなく、DTOで「ViewModelを使用する必要がある」と考えている人がいる場合は、かなり長い間その道を進んでいます(EntityFrameworkとMVC3:関係を変更できませんでした) 1つ以上の外部キープロパティがnull不可であるため)、これまでのところ、これを実現し、同じビューでアイテムを追加および削除する方法を明示的に示した人は誰もいません。コレクションのインデックスの維持に問題があるか、EntityFrameworkで保存できません...そしてコードは悪夢になりました。

このようにして、少なくとも理解できるコードがあります。唯一のことは、この追加を「通常の」順序で実行する必要があることです。つまり、コレクションの最後に追加します...

何か案は?

ところで:

これは機能しますが、最初に新しいプログラムをConsultantオブジェクトに追加し、新しいプログラムなしでViewModelを作成してから、個別にViewModelに追加する必要はないようです...

    public ActionResult NewProgram(int id)
    {
        //TODO: ordering is rather strange, because the entitycollection adds at the beginning rather than the end...
        Consultant consultant = _repository.GetConsultant(id);
        var vm = GetViewModel(consultant);
        var program = new Program();
        consultant.Programs.Add(program); 
        _repository.Save();
        vm.Programs.Add(program);
        return PartialView("ProgramList", vm);
    }
4

1 に答える 1

1

http://blogs.msdn.com/b/adonet/archive/2009/12/22/poco-proxies-part-1.aspxによると、ナビゲーションプロパティProgramsは、ある種のDoLazyLoad()メソッドを呼び出すためにオーバーライドされます。プロパティインスタンス自体は必ずしも変更されていないため、DoLazyLoad()実際には非同期である可能性があります。これにより、気付いている動作が説明される可能性があります。

ToList()とにかくリストを評価しているので、新しいプログラムを追加する前に呼び出すことができます。行を少し変更するだけで済みます。

consultant.Programs.ToList().Add(new Program());

これが機能しない場合は、次を試してください。

consultant.Programs.ToList();
consultant.Programs.Add(new Program());

これは実際には私の「非同期」理論ではうまく機能しませんが、役立つかもしれません。

于 2011-02-28T22:28:07.313 に答える