6

StackOverflow、Google、asp.netを調べて、これを行う方法の基本的な例を明確に見つけようとしています。すべての例は抽象的であるか、当てはまらない複雑な問題を含んでいます。私はそれらから多くの有用なものを抽出することができませんでした。これまでのところ、それらのどれも私の質問に完全に答えたり、私の問題に対処したりしていません。

私は次のモデルでMVCプロジェクトに取り組んでいます:

Article.cs:

public class Article
{

    public int ArticleId { get; set; }
    public string Title { get; set; }
    .
    .
    .
    public virtual ICollection<Category> Categories { get; set; }

    public Article()
    {
        Categories = new HashSet<Category>();
    }
}

Category.cs:

public class Category
{
    public int CategoryId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Article> Articles { get; set; }

    public Category()
    {
        Articles = new HashSet<Article>();
    }
}

ArticleEntities.cs:

public class ArticleEntities : DbContext
{
    public DbSet<Article> Articles { get; set; }
    public DbSet<Category> Categories { get; set; }

}

記事には多くのカテゴリを含めることができ、カテゴリは多くの記事に属することができます。

これまでのところ、カテゴリを除くすべての記事フィールドを保存/更新/作成できます。

ビューのチェックボックスとしてそれらを表しています。選択したチェックボックスの値をコントローラーに取得できますが、記事とともにデータベースに保存しようとしても失敗しました。

どうすればよいですか:

1)編集した記事を保存するときに、重複を作成せずにリレーションテーブルの既存のリレーションを更新しますか?

2)新しい記事を保存するときに、リレーションテーブルに選択したリレーションを作成しますか?

4

1 に答える 1

10

CategoryId私はあなたがコントローラーのポストアクションからsのリストを取得すると仮定しList<int>ますIEnumerable<int>

1)編集した記事を保存するときに、重複を作成せずにリレーションテーブルの既存のリレーションを更新しますか?

Article article; // from post action parameters
IEnumerable<int> categoryIds; // from post action parameters

using (var ctx = new MyDbContext())
{
    // Load original article from DB including its current categories
    var articleInDb = ctx.Articles.Include(a => a.Categories)
        .Single(a => a.ArticleId == article.ArticleId);

    // Update scalar properties of the article
    ctx.Entry(articleInDb).CurrentValues.SetValues(article);

    // Remove categories that are not in the id list anymore
    foreach (var categoryInDb in articleInDb.Categories.ToList())
    {
        if (!categoryIds.Contains(categoryInDb.CategoryId))
            articleInDb.Categories.Remove(categoryInDb);
    }

    // Add categories that are not in the DB list but in id list
    foreach (var categoryId in categoryIds)
    {
        if (!articleInDb.Categories.Any(c => c.CategoryId == categoryId))
        {
            var category = new Category { CategoryId = categoryId };
            ctx.Categories.Attach(category); // this avoids duplicate categories
            articleInDb.Categories.Add(category);
        }
    }

    ctx.SaveChanges();
}

プロパティ名が同じ(任意の)ArticleViewModelである場合、コードの代わりにを使用する場合にもコードが機能することに注意してください。ArticleSetValuesobject

2)新しい記事を保存するときに、リレーションテーブルに選択したリレーションを作成しますか?

上記とほぼ同じアイデアですが、データベース内の元の状態と比較する必要がないため、より単純です。

Article article; // from post action parameters
IEnumerable<int> categoryIds; // from post action parameters

using (var ctx = new MyDbContext())
{
    foreach (var categoryId in categoryIds)
    {
        var category = new Category { CategoryId = categoryId };
        ctx.Categories.Attach(category); // this avoids duplicate categories
        article.Categories.Add(category);
        // I assume here that article.Categories was empty before
    }
    ctx.Articles.Add(article);

    ctx.SaveChanges();
}
于 2012-07-08T18:48:51.930 に答える