Code First EF6 - 更新 MVC Web 应用程序中的多对多关系
Code First EF6 - Update Many-To-Many Relationship in MVC Web Application
我在 Courses 和 Ingredients 之间存在多对多关系,在 Meals 和 Courses 之间存在一对多关系。
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;
}
}
在膳食创建视图中,我可以为膳食添加课程,并为课程添加配料。一切正常。
但是,当我尝试编辑一顿饭时,none 的课程成分更改会被保存,并且不会抛出任何异常。
我的视图使用在编辑器模板中生成的下拉列表来填充 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.
标记每种成分
我所做的一切似乎都没有用,我几乎遍历了所有 Whosebug post 我能找到的关于该主题的内容(其中大部分归结为上述三种解决方案之一)。
如何正确保存这些关系?
目前,我的更新函数是这样的:
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 的连接 table。我做了一个快速测试模型
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();
}
}
并以
结尾
我在 Courses 和 Ingredients 之间存在多对多关系,在 Meals 和 Courses 之间存在一对多关系。
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;
}
}
在膳食创建视图中,我可以为膳食添加课程,并为课程添加配料。一切正常。
但是,当我尝试编辑一顿饭时,none 的课程成分更改会被保存,并且不会抛出任何异常。
我的视图使用在编辑器模板中生成的下拉列表来填充 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.
标记每种成分我所做的一切似乎都没有用,我几乎遍历了所有 Whosebug post 我能找到的关于该主题的内容(其中大部分归结为上述三种解决方案之一)。
如何正确保存这些关系?
目前,我的更新函数是这样的:
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 的连接 table。我做了一个快速测试模型
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();
}
}
并以