【问题标题】:Entity Framework & MVC Models实体框架和 MVC 模型
【发布时间】:2011-08-18 05:37:43
【问题描述】:

我们的团队目前正在开发一个 Web 应用程序,因为我们有一个添加了 Entity Framework .edmx 的类库并生成了 POCO 类。

我们的 Web 应用程序基于 MVC,我们在具有相同名称和属性的模型中定义了我们的类(从 .edmx 复制粘贴 POCO 类)。 .edmx 类库被引用到 MVC Web 应用程序。

视图是 MVC 模型类的强类型。我们使用 MVC 模型进行显示、字符串长度和必需。

在我们的控制器中,当有一个 CRUD 操作时,我们接受 POCO 类类型,例如

     public ActionResult Create(EFModels.User user)    {    }

EFModels.User 是 .edmx(POCO 生成的类)中的一个类,MVC 视图被强类型化为模型,即 MvcWebApplication.Models.User。

问题是我们如何在 ActionResult Create 中从 MvcWebApplication.Models.User(来自 Model)获取数据到 EFModels.User(EF 类)??

我能够获取数据,我知道它是相同的属性名称。我尝试更改类名,但它仍然有效,但如果我们更改属性名,它就不起作用。我无法理解其背后的逻辑。

最初我们不知道它不起作用,我们使用 AutoMapper 将模型类转换为 Edmx POCO 类。

任何想法,谢谢。

问题是我们如何通过任何映射将模型类的值传递给 EF 类。我不需要使用 AutoMapper,无需使用它即可获取值。

看看代码,希望解释得更好...

//POCO类

namespace EFModels
{
    using System;
    using System.Collections.Generic;

    public partial class User
    {
        public int Id { get; set; }
        public string Type { get; set; }
        public string Name { get; set; }
    }
}

//MVC模型类

namespace MvcWebSamp.Models
{
    public class User
    {
        public int Id { get; set; }

        [Display(ResourceType = typeof(BasicTags), Name = "Type")]
        [StringLength(15, ErrorMessageResourceName = "TypeLength", ErrorMessageResourceType = typeof(BasicTags))]
        [Required(ErrorMessageResourceName = "TypeRequired", ErrorMessageResourceType = typeof(BasicTags))]
        public string TypeName { get; set; }
        public string Name { get; set; }

        public Address Address { get; set; }
    }
}

//MVC查看页面

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcWebSamp.Models.User>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    User
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>User</h2>
  <% using (Html.BeginForm("Create", "User", FormMethod.Post))
       { 
    %>
     <%: Html.ValidationSummary(true) %>
    <fieldset>
        <legend>User</legend>
        <div class="editor-field">
            <%: Html.LabelFor(model => model.TypeName) %>
            <%: Html.EditorFor(model => model.TypeName)%>
            <%: Html.ValidationMessageFor(model => model.TypeName)%>
        </div>
        <div class="editor-field">
            <%: Html.LabelFor(model => model.Name) %>
            <%: Html.EditorFor(model => model.Name)%>
             <%: Html.EditorFor(model => model.Address.street)%>
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
    <% } %>
</asp:Content>

//控制器方法

 public ActionResult Create(EFModels.User user)
    {
        Model1Container con = new Model1Container();
        con.Users.Add(user);
        con.SaveChanges();
        return View("User");
    }

当我点击创建按钮时,我发布了 MvcWebSamp.Models.User 类型的数据,并且在创建操作中,我能够在不使用任何 AutoMapper 的情况下获取 EFModels.User 用户类型的数据。我想知道这是怎么回事???

【问题讨论】:

  • 你不应该在你的 UI 中使用你的 EF 模型。

标签: c# asp.net-mvc entity-framework c#-4.0 entity-framework-4.1


【解决方案1】:

您应该使用视图模型作为创建方法的参数类型:

[HttpPost]
public ActionResult Create(UserViewModel model)
{
    if (ModelState.IsValid)
    {
        int id = UserService.CreateFromViewModel(model);
        return RedirectToAction("View", new { id });
    }

    return View(model);
}

您的控制器应该被设计为创建和接受视图模型,并将它们传递给与您的数据层交互的适当服务以创建您的域模型。这使您的控制器操作非常精简。

您可以在服务中使用AutoMapper 之类的东西来轻松地在视图模型和域模型之间进行映射:

var user = Mapper.Map<UserViewModel, User>(model);

【讨论】:

    【解决方案2】:

    通过将 DbContext 提供给 UI 层,您正在创建 UI 和数据库之间的依赖关系。尝试将其分离并使用存储库模式和依赖注入。

    参考: http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx

    http://prodinner.codeplex.com/releases/view/66899
    

    【讨论】:

    • +1 这是个好建议。不要将 DAL 实体框架模型重新用于 MVC 模型,会出现问题。
    【解决方案3】:

    您根本没有使用您的MvcWebSamp - 正如您所看到的,控制器采用了EFModel

    public ActionResult Create(EFModels.User user)
    

    之所以有效,是因为属性相同。您只需修改控制器方法签名以取而代之的是 MvcWebSamp 对象,然后将这些对象转换为 EFModel 对象。

    【讨论】:

    • 由于我直接获取 EFModels.User 用户对象,我不必使用 AutoMapper。要转换我必须使用 AutoMapper,这会影响性能吗???。我使用 MvcWebSamp 模型的唯一原因是创建注释、必填字段和标签。我在 edmx 类中创建了注释、req 字段和标签,但是在编译 edmx 时,它会重新生成其类,并且声明的注释和其他项目将丢失。有什么解决方法吗?
    • 是的 - 解决方法是为 EFModel / edmx 类编写部分类。您可以添加 MetadataAttribute 以将属性应用于生成的类中的属性,例如 How To Add Metadata ClassesAdding Attributes To Generated Classes
    • 首选的、可维护的和可扩展的模式是像您一样使用单独的类 - 来自 EF 的数据类,然后是前端的 ViewModel 类。但是,如果您刚刚开始并且正在使用一个相当基本的模式,我认为从头到尾使用 edmx 类没有任何问题 - 如果需要,稍后将它们换掉是相当简单的。
    • 谢谢,引用元数据属性解决了问题,这是正确的。
    【解决方案4】:

    Automapper 应该可以工作。即使使用不同的属性名称,我们也会一直使用它。请发布对您不起作用的自动映射器的使用情况。否则请参阅以下帖子以使其适用于不同的属性名称。

    Usage of Automapper when property names are different

    【讨论】:

      【解决方案5】:

      为了使用实体框架,您需要创建一个实体数据模型。添加实体模型:

      1) 在解决方案资源管理器中右键单击模型文件夹。 2) 选择添加新项目。

      更多详情请查看以下链接....

      http://www.mindstick.com/Articles/6f3bb3c6-d195-487b-8b82-244bb417b249/?Model%20classes%20with%20Entity%20Framework%20in%20MVC

      谢谢!!!

      【讨论】:

        猜你喜欢
        • 2011-07-22
        • 2014-06-21
        • 2013-09-18
        • 1970-01-01
        • 1970-01-01
        • 2014-08-06
        • 2014-01-18
        • 1970-01-01
        • 2010-09-25
        相关资源
        最近更新 更多