Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何首先在EntityFramework代码中将一个模型映射到另一个模型的列表_C#_Asp.net Mvc_Entity Framework_Ef Code First - Fatal编程技术网

C# 如何首先在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

我有一个项目,其中我首先使用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 { 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());
}