如何使用EntityFramework为CRUD操作实现通用MVC Web控制器和通用视图

时间:2015-07-11 12:28:13

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

我正在研究.NET MVC WEB应用程序的设计,并确定我必须管理33个表(到目前为止)。通过管理我的意思是典型的SQL操作(插入,更新,删除和查询)

这33个表中有16个是需要使用典型CRUD方法处理的参考表。参考表我指的是其他表格引用并在组合中使用的表格(即国家,州,城市,货币等)

我对.NET中的MVC很新,但是看到当你使用脚手架时,你会得到具有典型方法的控制器:

  • 索引(获取)
  • 详细信息(获取)
  • 创建(获取+发布)
  • 编辑(获取+发布)
  • 删除(获取+发布)

同样在数据库方面,我计划使用EntityFramework实现INSERT,UPDATE,DELETE和LIST(查询操作)的典型DAO

以下是我的问题(最后; - )

由于50%的表格将以相同的方式在视觉和功能上进行管理并提供相同的CRUD操作是否有一种模式或方法可以实现最佳的代码/视图重用?

我想避免的是脚手架16个实体来获得16个控制器,每个控制器有16 * 5个视图(创建,删除,细节,编辑和索引)

是否可以让Single Main controller能够路由或管理所有这16个实体并调用实体所需的操作?

是否可以拥有足够通用的一组视图(创建,删除,详细信息,编辑和索引)来处理这16个实体?

如果以上两个是可能的,我将如何在Web项目的配置中连接路由,以便仍然能够为这16个实体中的每一个提供特定的URL(/ Countries / Edit / 5,/ States / Edit / 5等等)

以下是我认为可以实现这一目标的一种方式:

  • 为所有16个实体提供Abstract / Common基类或接口,其中包含管理EntityFramework上下文的Save,GetAll和Delete数据操作的逻辑(即IManageData)
  • 让EntityDao使用EntityFramework调用已实现IManageData的任何类的方法并执行操作。
  • 拥有一个抽象/公共基类(Web控制器),其中包含可以调用IManageData方法的所有16个实体的CRUD操作的通用逻辑

请帮我验证/完成我的设计草案,并提出一些注意事项或更好的方法来实现这一目标。

这里提供一些上下文是一个关于脚手架EntitieFramework实体与MVC项目https://code.msdn.microsoft.com/MVC5-Demo-with-Entity-c6bc81df

的approch的链接

这是一个非常类似的问题,我接受的答案是在确定如何实现这一目标之前要验证的。

Generic CRUD controllers and views

1 个答案:

答案 0 :(得分:5)

我之前的项目情况类似。我是这样做的。这是每个实体(表)的通用接口

public interface IRepository<T>
{
    void Add(T entity, User initiator);
    void Update(T entity, User initiator);
    void Delete(T entity);
    void Delete(int entityId);
    IEnumerable<T> GetAll();
    T GetById(int entityId);
}

可以使用Entity Framework(底部的代码示例,例如here )或使用不同的方法(在我的情况下,存储过程)轻松实现此常规数据层

我实际上没有任何额外的业务逻辑,所以我的web项目可以直接访问数据存储库。所以这是我的通用基础控制器

public abstract class BaseController<T, M> : Controller
    where M : new()
{
    public BaseController(IRepository<T> repository)
    {
        this._repository = repository;
        ViewBag.CurrentUser = CurrentUser;
    }

    protected User CurrentUser
    {
        get
        {
            if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
            {
                return Mapper.Map<User>(System.Web.HttpContext.Current.User.Identity);
            }
            return null;
        }
    }

    protected virtual int PageSize
    {
        get { return 5; }
    }

    protected IRepository<T> _repository;

    public virtual ActionResult Index(int? currentPage)
    {
        var entities = _repository.GetAll();
        List<M> model = new List<M>();

        foreach (var currentEntity in entities)
        {
            model.Add(Mapper.Map<M>(currentEntity));
        }

        int pageNumber = (currentPage ?? 1);
        return View(model.ToPagedList(pageNumber, PageSize));
    }

    [HttpGet]
    public virtual ActionResult Add()
    {
        return View(new M());
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    [ValidateInput(false)]
    public virtual ActionResult Add(M model)
    {
        if (ModelState.IsValid)
        {
            _repository.Add(Mapper.Map<T>(model), CurrentUser);
            return RedirectToAction("Index");
        }

        return View(model);
    }

    [HttpGet]
    public virtual ActionResult Update(int modelId)
    {
        T domainModelEntity = _repository.GetById(modelId);
        M model = Mapper.Map<M>(domainModelEntity);

        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    [ValidateInput(false)]
    public virtual ActionResult Update(M model)
    {
        if (ModelState.IsValid)
        {
            _repository.Update(Mapper.Map<T>(model), CurrentUser);
            return RedirectToAction("Index");
        }

        return View(model);
    }

    public virtual ActionResult Delete(int modelId)
    {
        _repository.Delete(modelId);
        return RedirectToAction("Index");
    }
}

这个特定的控制器

public class WebPagesController : BaseWebEntityController<WebPage, WebPageModel>
{
    public WebPagesController(IRepository<WebPage> repository)
        : base(repository)
    {
    }
}

一点解释。 a)您应该使用一些IOC进行控制器依赖性解析.b)T表示来自数据库(表)的实体,M表示返回给View.c的Model。)Automapper是众所周知的库。
我没有对路由做任何更改。保持默认。
希望能帮助到你。祝你好运。