Asp.net mvc 4 EF 5多对多在更新时正确创建领带,但在创建时不正确
我有一个使用MVC4和EF5的应用程序。我们有一个Asp.net mvc 4 EF 5多对多在更新时正确创建领带,但在创建时不正确,asp.net-mvc-4,entity-framework-5,Asp.net Mvc 4,Entity Framework 5,我有一个使用MVC4和EF5的应用程序。我们有一个Test对象,它通过在两侧设置导航属性,将导航多对多连接到Grades。这将按预期创建一个中间多对多联接表 测试: public virtual ICollection<Grade> Grades { get; set; } 由于应用程序和业务规则的自定义设计,我为操作创建了一个自定义模型绑定器,它将属性request.Form.GetValues(Grades)作为string[]并使用AddRange()方法将适当的等级添加到t
Test
对象,它通过在两侧设置导航属性,将导航多对多连接到Grades
。这将按预期创建一个中间多对多联接表
测试
:
public virtual ICollection<Grade> Grades { get; set; }
由于应用程序和业务规则的自定义设计,我为操作创建了一个自定义模型绑定器,它将属性request.Form.GetValues(Grades)
作为string[]
并使用AddRange()
方法将适当的等级添加到test.Grades
属性中,如下所示:
string[] values = request.Form.GetValues("Grades");
model.Grades.AddRange(context.Grades.Where(x => values.Contains(x.GradeLevel)).ToList();
这对于更新场景非常有效。但是,如果我的模型绑定器创建了一个新的测试
,那么结果是EF将新等级添加到等级
表中,然后使用新等级执行多对多联接,而不是使用现有等级
例如:
+-------------------+
| Grades before |
+--------+----------+
|GradeKey|GradeLevel|
+--------+----------+
| 1 | K |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
+--------+----------+
Assume that during creation of the test only grades 1 and 2 were
selected on the Add New Test screen
+-------------------+
| Grades after |
+--------+----------+
|GradeKey|GradeLevel|
+--------+----------+
| 1 | K |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | 1 |
| 6 | 2 |
+--------+----------+
然后将测试加入新等级(图例5和6),而不是原始等级(图例2和3)
为什么新测试与现有测试的这种行为不同
注意:我使用Test Test=new Test()尝试了这两种方法然后分配属性,以及testtest=newcontext.Tests.Add(newtest())代码>
编辑:
模型活页夹:
public class TestModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
HttpRequestBase request = controllerContext.HttpContext.Request;
Test model;
using (DataContext context = new DataContext())
{
if (!string.IsNullOrWhiteSpace(request.Form.Get("TestKey")))
{
int testkey = int.Parse(request.Form.Get("TestKey"));
model = context.Tests.Single(x => x.TestKey == testkey);
}
else model = context.Tests.Add(new Test());
...
if (request.Form.Get("Grades") != null)
{
string[] values = request.Form.GetValues("Grades");
model.Grades = context.Grades.Where(x => values.Contains(x.GradeLevel)).ToList();
}
...
}
return model;
}
}
控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Test test)
{
if (!ModelState.IsValid) return PartialView("_Create", test);
//DataService.Context.Tests.Add(test); # Removed since model is added in model binder
DataService.Context.SaveChanges();
return RedirectToAction("Index");
}
编辑和创建场景的完整代码(与EF相关)是什么样子的-从加载/附加/创建<代码>模型
到<代码>保存更改
?添加了模型绑定代码和控制器操作。我想知道为什么会保存任何内容。您在模型绑定器中有一个单独的上下文实例(使用(DataContext context=new DataContext())
),但不在此块中调用SaveChanges
,而是稍后在操作中调用DataService.context.SaveChanges()
。或者newdatacontext()
是否以某种方式返回与DataService.Context
相同的实例?否DataService.Context
是DataContext
的另一个实例。可能是DataService.Context.Tests.Add(test)
允许它工作,因为在我上次运行应用程序时它仍然存在。我最初只使用模型活页夹中的数据上下文
,这样我就可以提取正确的等级
记录。模型活页夹还用于编辑和创建操作
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Test test)
{
if (!ModelState.IsValid) return PartialView("_Create", test);
//DataService.Context.Tests.Add(test); # Removed since model is added in model binder
DataService.Context.SaveChanges();
return RedirectToAction("Index");
}