ASP.NET MVC无需使用Entity Framework

13

我正在学习asp.net mvc,并通过一篇很棒的教程进行了演示。该教程还使用了Entity Framework。

我们有自己的数据访问类,我必须使用它。 我有点困惑于如何在我们的类和MVC框架之间建立联系。 例如,在教程中,MovieController.cs文件中有一个Edit方法,看起来像这样:

[HttpPost]
        public ActionResult Edit(Movie movie)
        {
            if (ModelState.IsValid)
            {
                db.Entry(movie).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(movie);
        }
如果我不使用Entity Framework,会是什么样子?我仍然需要使用ModelState.IsValid并保存状态吗?
db.Entry(movie).State = EntityState.Modified;
请给予建议。提供一个清晰的例子,展示如何在不使用 Entity Framework 的情况下使用 asp.net mvc 很好。我需要知道状态在这里扮演的角色是什么,是否强制使用或只是 Entity Framework 运行方式的一部分。我会将其改写为:
[HttpPost]
public ActionResult Edit(Movie movie)
{
    myDBObject.SaveChanges();
    return RedirectToAction("Index");

}

其中 myDBObject 是我的自定义数据库访问对象。

4个回答

20

从外部看到的控制器直接使用一些数据访问框架(如Entity Framework)的示例是不好的示例。整个互联网都被这样的东西弄脏了。我几乎无法忍受看它而不使眼睛痛。我认为这些是不良实践。数据访问应该在存储库中分离和抽象化。例如:

public interface IMoviesRepository
{
    Movie Get(int id);
    void Save(Movie movie);
}

那么你可以使用普通的 ADO.NET、EF、NHibernate、远程 Web 服务调用、自定义 ORM 或其他方式来实现此接口:

public class MyCustomFrameworkMoviesRepository: IMoviesRepository
{
    ...
}

控制器将以这个仓库接口作为构造函数参数:

public class MoviesController: Controller
{
    private readonly IMoviesRepository _repository;
    public MoviesController(IMoviesRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index(int id)
    {
        var movie = _repository.Get(id);
        return View(movie);
    }

    [HttpPost]
    public ActionResult Index(Movie movie)
    {
        if (!ModelState.IsValid)
        {
            return View(movie);
        }

        _repository.Save(movie);
        return RedirectToAction("Success");
    }
}
并且最后一部分是配置你的依赖注入框架,以将正确的存储库实现传递到控制器。现在,正如您所看到的,数据获取的方式与控制器逻辑完全解耦。这就是应该的方式。始终尝试避免应用程序不同层之间的强耦合。
至于State属性的问题,这完全是EF特有的,像这样在控制器中看到这样的东西真的很遗憾。
为了进一步改进它,您可以引入视图模型。视图模型是专门设计以满足给定视图要求的类。因此,例如,电影是领域模型。领域模型不应直接传递给视图。控制器操作不应将领域模型作为操作参数。您应该定义仅包含给定视图所需内容的视图模型,然后执行视图模型和领域模型之间的映射。像 AutoMapper 这样的框架使这非常简单。

2
虽然我同意它们是不好的实践,但有时候不构建抽象的UnitOfWork/Repository模式可能是实际可行的。专业开发人员将遵循允许安全性、可扩展性和可测试性的模式... 公司IT人员或爱好者的需求可能无法证明这一点。 - Jeremy Holovacs
你能否回答一下这个问题:http://stackoverflow.com/questions/9328197/asp-net-mvc-3-automatically-generating-view-while-adding-controller-without-en? - LCJ
当你抽象出ORM时,你可能会失去特定ORM的优势,而倾向于未来可能(但非常不可能)的ORM切换。在ORM之上创建另一个抽象层几乎是不可能的(本身就是一个巨大的抽象层),并且仍然能够充分从中受益。实际上,你可能会将所有东西都降至最低限度,失去了惰性加载、预取和许多其他重要功能,以实现你的抽象。但不要听我的,阅读http://ayende.com/blog/3955/repository-is-the-new-singleton。 - Loudenvier
让我补充一下,我不赞成在视图/控制器中使用领域模型对象,我完全支持视图模型方法。我只是真的不认为将数据访问逻辑抽象到存储库中有多大价值,因为我们已经在现代、深思熟虑、成熟的ORM框架(如nHibernate的会话等)中拥有了非常强大的“存储库”。 - Loudenvier
那么 MyCustomFrameworkMoviesRepository 的实现在哪里发挥作用?我没有看到它。 - Mickey
显示剩余2条评论

2

嗯。

MVC和实体框架并没有什么关系,它们只是很好地协同工作。

if (ModelState.IsValid) 验证你的视图模型。如果你不使用带验证程序的视图对象,那么这有点毫无意义;如果你使用,那么它就非常有价值。

if (ModelState.IsValid) 括号内,你会获取来自web页面的POST数据(通常是一个视图模型),并将其应用于将其持久化到数据库的对象。EF经常被使用,因为一旦设置好,它就相当容易维护,而且需要编写的代码也更少。

            db.Entry(movie).State = EntityState.Modified;
            db.SaveChanges();

这两个和EF有关。它们需要被你的存储库类方法和对象所替换。

            return RedirectToAction("Index");

是MVC。在成功持久化到数据存储后,返回控制到索引页面。

        return View(movie);

用于重定向回原始视图,因为某些内容未通过验证。


1

你仍然需要检查ModelState.IsValid,但除此之外,你的代码看起来就像你所拥有的。

这假设你的模型上有DataAnnotations属性,这就是ModelState.IsValid用于检查的内容。这些属性可以用于任何C#类的属性 - 不仅仅是Entity Framework。

你可能最终会为此创建特定的视图模型。


假设我编写了一个自定义类,用于从数据库中提取数据并传递给模型。在搜索时,我发现了这个信息:“你可以使用ADO.NET代码替换实体,并从数据库层返回一个列表对象/可枚举对象。然后,可以将其作为模型传递给视图。” - sarsnake

0

你需要在电影对象(通过http POST传递)和你的数据库方法(myDBObject)之间建立一些连接。

也许你想说myDBObject.SaveChanges(movie),假设你的数据库代码知道如何处理Movie对象,那么你就没问题了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接