C# 如何首先在EntityFramework代码中将一个模型映射到另一个模型的列表
我有一个项目,其中我首先使用EntityFramework代码来管理数据库。 我使用的模型如下所示:C# 如何首先在EntityFramework代码中将一个模型映射到另一个模型的列表,c#,asp.net-mvc,entity-framework,ef-code-first,C#,Asp.net Mvc,Entity Framework,Ef Code First,我有一个项目,其中我首先使用EntityFramework代码来管理数据库。 我使用的模型如下所示: [Table("Data")] public class Data { [Key, Column("Id")] public int Id { get; set; } [Column("Code")] public string Code { get; set; } [Column("Name")] public string Name { g
[Table("Data")]
public class Data
{
[Key, Column("Id")]
public int Id { get; set; }
[Column("Code")]
public string Code { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Description")]
public string Description { get; set; }
public virtual List<DataAttribute> Attributes { get; set; }
}
我遇到的问题是当我试图编辑一个数据对象(及其相关的DataAttribute值)时。在提交包含数据元素和DataAttribute元素的表单时,我没有使其正确映射。我给出了一个.cshtml文件的示例
@model MVCTestApp.Models.Data
@{
ViewBag.Title = "Edit";
}
@section Scripts {
<script type="text/javascript">
$(function () {
$('#new-row').click(function () {
$('table tbody').append(
'<tr>' +
'<td><input class="name" type="text" /></td>' +
'<td><input class="description" type="text" /></td>' +
'<td><a class="delete" href="#">Delete</a></td>' +
'</tr>'
);
$('.delete').click(function () {
$(this).parent().parent().remove();
});
});
});
</script>
}
@using (@Html.BeginForm("Edit", "Data", FormMethod.Post)) {
@Html.HiddenFor(a => a.Id)
Name:
<br />
@Html.TextBoxFor(a => a.Name)
<br />
Description:
<br />
@Html.TextBoxFor(a => a.Description)
<br />
Code:
<br />
@Html.TextBoxFor(a => a.Code)
<br />
<table>
<thead>
<tr>
<th>
Name
</th>
<th>
Description
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a id="new-row" href="#">New Row</a>
</td>
<td colspan="2">
</td>
</tr>
@if (Model != null) {
foreach (var item in Model.Attributes) {
<tr>
@Html.HiddenFor(b => item.Id)
@Html.HiddenFor(b => item.IdData)
<td class="name">@Html.TextBoxFor(b => item.Name)
</td>
<td class="description">@Html.TextBoxFor(b => item.Description)
</td>
<td>
<a class="delete" href="#">Delete</a>
</td>
</tr>
}
}
</tbody>
</table>
<input type="submit" value="submit" />
}
先谢谢你。首先你需要了解一些事情。 第一个问题是,为什么代码优先?您没有告诉我们为什么不构建sql模型并使用EF工具导入。 然后,您需要了解ModelBinder机制是如何工作的。您发送一个带有参数的HTTPPOST请求,每个参数都有一个名称,并希望将其绑定到一个模型类。ModelBinder尝试在模型类中查找这些名称,如果有大量同名参数,则这种情况永远不会发生。这种属性也被称为导航属性,它们应该由EF或以单独的形式加载 例如,您正在尝试使用一个表单来构建一个包含许多DataAttributes的数据对象。为什么不先创建数据对象,然后在另一个视图中添加DataAttibutes? 这就是MVC的意义所在。不同的模型->不同的控制器->不同的视图
如果你不将责任分开,你将面临更多的麻烦。为了解决这个问题,我做了以下工作:将视图上的foreach改为for和used属性[I],以便它使用它来创建输入(这就是控制器实际接收值的原因)我还改变了创建新行的方式,以便它们也使用相同的命名约定并传递给控制器 以下是新的观点:
@model MVCTestApp.Models.Data
@{
ViewBag.Title = "Edit";
}
@section Scripts {
<script type="text/javascript">
$(function () {
$('#new-row').click(function () {
var counter = $("#counter").val();
counter++;
$('table tbody').append(
'<tr>' +
'<td><input id="Attributes_' + counter + '__Name" ' +
'name="Attributes[' + counter + '].Name" type="text" /></td>' +
'<td><input id="Attributes_' + counter + '__Description" ' +
'name="Attributes[' + counter + '].Description" type="text" /></td>' +
'<td><a class="delete" href="#">Delete</a></td>' +
'</tr>'
);
$('.delete').click(function () {
$(this).parent().parent().remove();
});
$("#counter").val(counter);
});
});
</script>
}
@using (@Html.BeginForm("Edit", "Data", FormMethod.Post)) {
var counter = 0;
@Html.HiddenFor(a => a.Id)
Name:
<br />
@Html.TextBoxFor(a => a.Name)
<br />
Description:
<br />
@Html.TextBoxFor(a => a.Description)
<br />
Code:
<br />
@Html.TextBoxFor(a => a.Code)
<br />
<table>
<thead>
<tr>
<th>
Name
</th>
<th>
Description
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a id="new-row" href="#">New Row</a>
</td>
<td colspan="2">
</td>
</tr>
@if (Model != null) {
for (int i = 0; i < Model.Attributes.Count; i++) {
<tr>
@Html.HiddenFor(a => a.Attributes[i].Id)
@Html.HiddenFor(a => a.Attributes[i].IdData)
<td>@Html.TextBoxFor(a => a.Attributes[i].Name)</td>
<td>@Html.TextBoxFor(a => a.Attributes[i].Description)</td>
<td>
<a class="delete" href="#">Delete</a>
</td>
</tr>
counter = i;
}
}
</tbody>
</table>
<input type="submit" value="submit" />
@Html.Hidden("counter", counter.ToString());
}
@model MVCTestApp.Models.Data
@{
ViewBag.Title=“编辑”;
}
@节脚本{
$(函数(){
$(“#新行”)。单击(函数(){
var counter=$(“#counter”).val();
计数器++;
$('table tbody')。追加(
'' +
'' +
'' +
'' +
''
);
$('.delete')。单击(函数(){
$(this.parent().parent().remove();
});
$(“#计数器”).val(计数器);
});
});
}
@使用(@Html.BeginForm(“编辑”、“数据”、FormMethod.Post)){
var计数器=0;
@Html.HiddenFor(a=>a.Id)
姓名:
@Html.TextBoxFor(a=>a.Name)
说明:
@Html.TextBoxFor(a=>a.Description)
代码:
@Html.TextBoxFor(a=>a.Code)
名称
描述
@如果(型号!=null){
对于(int i=0;ia.Attributes[i].Id)
@Html.HiddenFor(a=>a.Attributes[i].IdData)
@Html.TextBoxFor(a=>a.Attributes[i].Name)
@Html.TextBoxFor(a=>a.Attributes[i].Description)
计数器=i;
}
}
@Html.Hidden(“counter”,counter.ToString());
}
将列表发送回控制器时,需要确保列表的序列化。您还可以尝试设置返回的包含列表的特定ViewModel。我如何序列化它?方法是将其设置为json对象或类似的对象,然后将其传递给控制器?这很容易实现,我要做的是向ActionResult添加一个参数并将其设置为string,然后使用内置的json解析器获取值并设置models属性。您可以在客户端上使用JSON来序列化要发送回的对象。实际上,我一直在使用JSON,但是在实际将模型保存到db时,我遇到了很多问题。我将继续尝试ViewModel方法。谢谢。在我看来,这使事情更容易维护。我们首先使用代码,因为我们将对数据库进行大量更改,重新创建edmx文件并将其更新到服务器将花费太长的时间,使其无法发挥作用。我也在同一个页面上处理数据和数据属性,因为数据属性只存在于数据内部进行修改,它们是数据的一部分,而且(对我来说)创建另一个控制器、视图和所有内容来编辑它们没有什么意义。我目前正在尝试正确地创建它们,以便将它们传递回控制器,我想我已经找到了方法,如果正确,将发布您的解决方案不是很好。你正在创建一个毫无意义的新模型。无法保证DataEdit对象中的DataAttributes属于数据。是的,你可以制作舒尔,但用户可以强迫黑客。您只是添加了一个不存在的新模型。你应该重新思考MVC是如何工作的,它代表了什么,以及如何构建你的应用程序。这是一个解决方法,不是解决方案。我会再仔细考虑一下,ViewModel不应该是必需的,你是对的,但从用户的角度来看,功能确实是有意义的。去掉ViewModel后,它会起作用,会更新我的答案。我仍然认为模型应该分开,但如果你真的想这样做,是的,这是一个解决办法。我想你可能会有麻烦,删除取决于你将如何使用它,但它似乎n
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Data model)
{
if (model != null) {
db.Data.Add(model); //model has the model.Attributes list set as null
db.SaveChanges();
return View("Index", db.Data.OrderBy(a => a.Id).ToList());
}
return View();
}
@model MVCTestApp.Models.Data
@{
ViewBag.Title = "Edit";
}
@section Scripts {
<script type="text/javascript">
$(function () {
$('#new-row').click(function () {
var counter = $("#counter").val();
counter++;
$('table tbody').append(
'<tr>' +
'<td><input id="Attributes_' + counter + '__Name" ' +
'name="Attributes[' + counter + '].Name" type="text" /></td>' +
'<td><input id="Attributes_' + counter + '__Description" ' +
'name="Attributes[' + counter + '].Description" type="text" /></td>' +
'<td><a class="delete" href="#">Delete</a></td>' +
'</tr>'
);
$('.delete').click(function () {
$(this).parent().parent().remove();
});
$("#counter").val(counter);
});
});
</script>
}
@using (@Html.BeginForm("Edit", "Data", FormMethod.Post)) {
var counter = 0;
@Html.HiddenFor(a => a.Id)
Name:
<br />
@Html.TextBoxFor(a => a.Name)
<br />
Description:
<br />
@Html.TextBoxFor(a => a.Description)
<br />
Code:
<br />
@Html.TextBoxFor(a => a.Code)
<br />
<table>
<thead>
<tr>
<th>
Name
</th>
<th>
Description
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a id="new-row" href="#">New Row</a>
</td>
<td colspan="2">
</td>
</tr>
@if (Model != null) {
for (int i = 0; i < Model.Attributes.Count; i++) {
<tr>
@Html.HiddenFor(a => a.Attributes[i].Id)
@Html.HiddenFor(a => a.Attributes[i].IdData)
<td>@Html.TextBoxFor(a => a.Attributes[i].Name)</td>
<td>@Html.TextBoxFor(a => a.Attributes[i].Description)</td>
<td>
<a class="delete" href="#">Delete</a>
</td>
</tr>
counter = i;
}
}
</tbody>
</table>
<input type="submit" value="submit" />
@Html.Hidden("counter", counter.ToString());
}