繁体   English   中英

代码优先EF6-更新MVC Web应用程序中的多对多关系

[英]Code First EF6 - Update Many-To-Many Relationship in MVC Web Application

我在课程和配料之间有多对多的关系,在膳食和课程之间有一对多的关系。

public MealContext _context = new MealContext();
public IEnumerable<Meal> Meals { get { return  _context.Meals.Include("Courses"); } }
public IEnumerable<Course> Courses { get { return   _context.Courses.Include("Ingredients"); } }
public IEnumerable<Ingredient> Ingredients { get { return _context.Ingredients; }

public class BaseEntity
{
    public int Id { get; set; }
    public DateTime Created { get; set; }
    public DateTime Updated { get; set; }
}

public class Meal : BaseEntity
{
    public string Name { get; set; }
    public List<Course> Courses { get; set; }
}

public class Course : BaseEntity
{
    public string Name { get; set;}
    public Meal Meal { get; set; }
    [ForeignKey("Ingredients")]
    public List<int> IngredientIds { get; set; }
    public List<Ingredient> Ingredients { get; set; }
}

public class Ingredient : BaseEntity
{
    public string Name { get; set; }
}

public bool AddMeal(ref Meal meal)
{
    try
    {
        _context.Meals.Add(meal);
        foreach (var course in meal.Courses)
        {
            course.Created = DateTime.Now;
            course.Updated = DateTime.Now;

            _context.Courses.Add(course);
            if(course.Ingredients == null) { course.Ingredients = new List<Ingredient>(); }
            foreach (var ingredient in course.Ingredients)
            {
                _context.Entry(ingredient).State = EntityState.Modified;
            }
        }
        meal.Created = DateTime.Now;
        meal.Updated = DateTime.Now;
        _context.SaveChanges();
        trans.Commit();
        return true;
    }
    catch (Exception ex)
    {
        Logger.Error(ex.Message + "\n" + ex.StackTrace);
        trans.Rollback();
        return false;
    }
}        

在进餐创建视图上,我可以在进餐中添加课程,并在课程中添加配料。 一切正常。

但是,当我尝试编辑一顿饭时,课程的任何成分更改都不会保存,也不会抛出异常。

我的视图使用在编辑器模板中生成的下拉列表来填充IngredientIds集合,并且我已验证该列表在到达我的存储库时已被填充且正确。

我试过从数据库加载每个课程对象,使用_context.Entry(dbCourse).CurrentValues.SetValues(course)将跟踪对象的每个值设置为未跟踪对象的值。

我已经尝试通过ID(course.Ingredients = _context.Ingredients.Where(i => course.IngredientIds.Contains(i.Id));)从数据库将配料加载到列表中。

我尝试使用_context.Entry(ingredient).State = EntityState.Modified标记每种成分。

我似乎什么都没做,而且我已经仔细阅读了我在该主题上能找到的每一个StackOverflow帖子(其中大部分归结为上述三个解决方案之一)。

如何获得这些关系以正确保存?

目前,我的更新功能如下所示:

public bool UpdateMeal(ref Meal meal)
{
    using (var trans = _context.Database.BeginTransaction())
    {
        try
        {
            meal.Updated = DateTime.Now;
            if (meal.Courses != null)
            {
                foreach (var course in meal.Courses)
                {
                    course.Updated = DateTime.Now;
                    if (course.IngredientIds != null && course.IngredientIds.Count > 0)
                    {
                        var newIngredients = _context.Ingredients.Where(i => course.IngredientIds.Contains(i.Id)).ToList();
                        course.Ingredients = newIngredients;
                    }
                    var dbCourse = _context.Courses.Include("Ingredients").Single(c => c.Id == course.Id);
                    _context.Entry(dbCourse).CurrentValues.SetValues(course);
                }
            }
            _context.SaveChanges();
            trans.Commit();
            return true;
        }
        catch (Exception ex)
        {
            Logger.Error(ex.Message + "\n" + ex.StackTrace);
            trans.Rollback();
            return false;
        }
    }
}

我将有助于将导航属性更改为virtual以便Entity Framework可以创建延迟加载代理。

例:

public virtual List<Ingredient> Ingredients { get; set; }
public virtual Meal Meal { get; set; }

您可能需要告诉EF您的关系。 这样做,将流动方法添加到您的DbContext中:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // One to many
    modelBuilder.Entity<Meal>()
        .HasMany(x => x.Courses)
        .WithRequired(x => x.Meal);

    // Many to many
    modelBuilder.Entity<Course>()
        .HasMany(x => x.Ingredients)
        .WithMany();
}

课程需要virtual ICollection<Ingredient>而成分需要virtual ICollection<Course> EF应该创建一个联接表,称为IngredientCourses或CourseIngredients。 我做了一个快速测试模型

public class Meal
    {
        public int Id { get; set; }
        public virtual ICollection<Course> Courses { get; set; }
    }

    public class Course
    {
        public int Id { get; set; }
        public int MealId { get; set; }
        public virtual Meal Meal{ get; set; }
        public virtual ICollection<Ingredient> Ingredients { get; set; }
    }

    public class Ingredient
    {
        public int Id { get; set; }
        public virtual ICollection<Course> Courses { get; set; }
    }

并制作了一顿新饭。

    private void OnLoaded(object sender, RoutedEventArgs e)
    {
        using (var context = new MealContext())
        {
            var meal = new Model.Meal();
            var course = new Model.Course();
            var ingredient = new Model.Ingredient();
            var ingredient2 = new Model.Ingredient();
            course.Ingredients = new[] { ingredient, ingredient2 };
            meal.Courses = new[] { course };
            context.Meals.Add(meal);
            context.SaveChanges();
        }
    }

并最终以 在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM