5

私は一般的に C# と MVC に非常に慣れておらず、テスト プロジェクトとして自分の小さなブログ サイトを作成しています。ここまではほとんど問題なく動作していますが、LINQ クエリから複数の列を選択する際に問題が発生しました。これを処理するために、生成されたエンティティ クラスを厳密に型指定されたモデルとして使用できることに気付いたのは、SO に関する質問に出くわした後でした。データベース層を作成しており(これも以前に使用したことがないものです)、その層を介して匿名型を渡そうとしても機能しなかったため、これが必要でした。なぜそうなったのかは理解できたので、正しい方向に向かっていることに満足しています。

しかし、このアプローチは私に別の問題を与えたようです。Categories テーブルから 2 つの列 (CategoryID と Name) を取得する簡単なテストを試みました。私は最初に次のことを試しました:

using (MyEntities db = new MyEntities())
{
    var model = from c in db.Categories
                select new Category { CategoryID = c.CategoryID, Name = c.Name };

    return View(model);
}

これにより、ビュー内のモデルを反復処理しようとすると、ObjectContext が破棄されたというエラーが発生しました。この質問を読んだ後、return ステートメントを using ブロックの外に移動し、次のようにモデルで AsEnumerable() を呼び出してみました。

IEnumerable<Category> model;

using (MyEntities db = new MyEntities())
{
    model = from c in db.Categories
            select new Category { CategoryID = c.CategoryID, Name = c.Name };
}

return View(model.AsEnumerable());

ただし、ビューでモデルを反復しようとすると、同じ ObjectContext が破棄されたというエラーが引き続き表示されます。だから今、私はなぜエラーが発生しているのか理解できません。using ディレクティブを完全に削除しようとしましたが、別のエラーが発生します。

「エンティティまたは複合型 'MyProjectModel.Category' は、LINQ to Entities クエリで構築できません。」

それが役立つ場合は、私のビューに関連するコードを次に示します。

@model IEnumerable<MyProject.Models.Category>

@foreach (var category in Model)
{
    <p>@category.Name</p>
}

誰かが私に足りないものを教えてくれますか?

ありがとう。

4

1 に答える 1

12

.ToList()ブロックを離れる直前にクエリの実行をスケジュールするために、破棄する前にコントローラーで熱心に呼び出しますusing(その後では手遅れなので、コンテキストは失われます)。

using (MyEntities db = new MyEntities())
{
    var model = 
        from c in db.Categories
        select new Category 
        { 
            CategoryID = c.CategoryID, 
            Name = c.Name 
        };
    return View(model.ToList()); // <-- .ToList() here
}

これで特定の問題は解決しますが、開発者または依存性注入フレームワークが通常行うことは、イベントDbContext内で をインスタンス化し、それを 内に格納して、リクエスト全体の実行中およびメソッド内で使用できるようにし、から取得することです。そして処分します。BeginRequestHttpContext.ItemsEndRequestHttpContext


アップデート:

また、この特定のビューで使用するプロパティのみを含むビュー モデルを使用することをお勧めします。

public class CategoryViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

そしてあなたの行動の中で:

public ActionResult Index()
{
    using (MyEntities db = new MyEntities())
    {
        var model = 
            from c in db.Categories
            select new CategoryViewModel
            { 
                Id = c.CategoryID, 
                Name = c.Name 
            };
        return View(model.ToList());
    }
}

そしてビューで:

@model IEnumerable<MyProject.Models.CategoryViewModel>

@foreach (var category in Model)
{
    <p>
        Id: @category.Id 
        Name: @category.Name
    </p>
}
于 2011-06-19T20:06:25.330 に答える