【问题标题】:MVC BaseController handling CRUD operationsMVC BaseController 处理 CRUD 操作
【发布时间】:2013-05-19 06:26:52
【问题描述】:

我想重构我的基本 CRUD 操作,因为它们非常重复,但我不确定最好的方法。我所有的控制器都继承了 BaseController,如下所示:

public class BaseController<T> : Controller where T : EntityObject
{
    protected Repository<T> Repository;

    public BaseController()
    {
        Repository = new Repository<T>(new Models.DatabaseContextContainer());
    }

    public virtual ActionResult Index()
    {
        return View(Repository.Get());
    }
}

我像这样创建新的控制器:

public class ForumController : BaseController<Forum> { }

很好,很简单,你可以看到我的BaseController 包含一个Index() 方法,这意味着我的控制器都有一个 Index 方法,并且将从存储库中加载它们各自的视图和数据——这非常有效。我在编辑/添加/删除方法上苦苦挣扎,我的存储库中的Add 方法如下所示:

public T Add(T Entity)
{
    Table.AddObject(Entity);
    SaveChanges();

    return Entity;
}

再次,很好很容易,但在我的BaseController 中我显然做不到:

public ActionResult Create(Category Category)
{
    Repository.Add(Category);
    return RedirectToAction("View", "Category", new { id = Category.Id });
}

我通常会这样做:有什么想法吗?我的大脑似乎无法通过这个.. ;-/

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-3


    【解决方案1】:

    您可以添加一个由所有实体共享的接口:

    public interface IEntity
    {
        long ID { get; set; }
    }
    

    让你的基本控制器需要这个:

    public class BaseController<T> : Controller where T : class, IEntity
    

    这将允许您:

    public ActionResult Create(T entity)
    {
        Repository.Add(entity);
        return RedirectToAction("View", typeof(T).Name, new { ID = entity.ID });
    }
    

    您还应该考虑使用依赖注入来实例化您的控制器,以便您的存储库被注入而不是手动实例化,但这是一个单独的主题。

    【讨论】:

    • 我已经尝试过了,但它似乎不起作用;我收到编译器错误,例如 Error 4 The type 'Models.Category' cannot be used as type parameter 'T' in the generic type or method 'Controllers.BaseController&lt;T&gt;'. There is no implicit reference conversion from 'Models.Category' to 'System.Data.Objects.DataClasses.EntityObject'.Error 3 The type 'Models.User' cannot be used as type parameter 'T' in the generic type or method 'Controllers.BaseController&lt;T&gt;'. There is no implicit reference conversion from 'Models.User' to 'Classes.Core.IEntity'. 我正在使用 EF4。
    • 您需要让您的实体实现 IEntity。即定义“class Category : IEntity”并在其上实现ID属性。
    • 如果您使用的是 EF,那么最好的方法是添加一个部分类“公共部分类类别:IEntity”并将 ID 属性添加到其中。请务必将其定义在与实体类相同的命名空间中。
    • 我想我需要睡觉 :-) 非常感谢 Morten,工作完美。
    【解决方案2】:

    不确定问题是什么,你不能让 CRUD 点也通用吗?

    public virtual ActionResult Create(T entity) where T : IEntity
    {
        Repository.Add(entity);
        return RedirectToAction("View", this.ModelType, new { id = entity.Id });
    }
    

    这假设:

    • 您的控制器在构建时会在基本控制器上设置一个名为“ModelType”的值,该值告诉它应该控制什么“类型”的模型。
    • 您有一个公共接口 (IEntity) 或已知的基类,它具有一组基本属性(如 Id),控制器可以使用这些属性来管理流参数等。

    我实际上并没有尝试过,但我已经完成了类似的脚手架,并且该模式运行良好。如果无法修改或扩展您的 POCO(或您正在使用的任何东西)对象模型,它可能会很棘手。

    【讨论】:

      猜你喜欢
      • 2018-12-09
      • 1970-01-01
      • 2016-12-16
      • 2014-07-09
      • 2018-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-27
      相关资源
      最近更新 更多