ASP.NET MVC3和Entity Framework code第一架构 [英] ASP.NET MVC3 and Entity Framework Code first architecture

查看:132
本文介绍了ASP.NET MVC3和Entity Framework code第一架构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的previous问题。

My previous question made me think again about layers, repository, dependency injection and architectural stuff like this.

我的架构现在看起来是这样的:结果
我使用EF code第一次,所以我只是做POCO类和背景。这造成db和模型。结果
水平高的业务层类(供应商)。我使用不同的供应商为每个域...像MemberProvider,RoleProvider,TaskProvider等等,我在这些供应商让我的DbContext的新实例。结果
然后我在控制器实例这些供应商,获取数据,并将它们发送到视图。

My architecture now looks like this:
I am using EF code first, so I just made POCO classes, and context. That creates db and model.
Level higher are business layer classes (Providers). I am using different provider for each domain... like MemberProvider, RoleProvider, TaskProvider etc. and I am making new instance of my DbContext in each of these providers.
Then I instantiate these providers in my controllers, get data and send them to Views.

我最初的架构包括库,这是我摆脱了,因为我被告知,这只是增加了复杂性,所以我为什么不单单只用EF。我想这样做,与EF工作..直接从控制器,但我必须写测试,它是与实际的数据库有点复杂。我不得不假 - 模拟数据不知何故。所以我做了每个提供商的接口,并提出在名单硬codeD数据假提供商。而与此我回来的东西,在这里我不知道如何正确地进行。

My initial architecture included repository, which I got rid of because I was told that it just adds complexity, so why I don't just use EF only. I wanted to did that.. working with EF directly from controllers, but I have to write tests and it was a bit complicate with real database. I had to fake - mock data somehow. So I made an interface for each provider and made fake providers with hardcoded data in lists. And with this I got back to something, where I am not sure how to proceed correctly.

这些东西开始被过快过于复杂......许多方法和pattterns...它只是创造太多的噪音和无用的code。

These things starts to be overcomplicated too quickly... many approaches and "pattterns"... it creates just too much noise and useless code.

是否有创建和使用实体框架?

推荐答案

如果你想使用TDD(或具有较高的测试覆盖率任何其他测试方法)和EF一起您必须编写整合或终端到终端的测试。这里的问题是,与嘲讽或者上下文或库中的任何方法只是创建测试,可以测试你的上层逻辑(使用那些嘲笑),而不是你的应用程序。

If you want to use TDD (or any other testing approach with high test coverage) and EF together you must write integration or end-to-end tests. The problem here is that any approach with mocking either context or repository just creates test which can test your upper layer logic (which uses those mocks) but not your application.

简单的例子:

让我们定义的通用存储库:

Let's define generic repository:

public interface IGenericRepository<TEntity> 
{
    IQueryable<TEntity> GetQuery();
    ...
}

和允许写一些商业方法:

And lets write some business method:

public IEnumerable<MyEntity> DoSomethingImportant()
{
    var data = MyEntityRepo.GetQuery().Select((e, i) => e);
    ...
}

现在,如果你嘲笑库中,您将使用LINQ到对象,你将有一个绿色的测试,但如果您运行使用LINQ到实体的应用程序,你会得到一个例外,因为使用索引选择超载不支持L2E。

Now if you mock the repository you will use Linq-To-Objects and you will have a green test but if you run the application with Linq-To-Entities you will get an exception because select overload with indexes is not supported in L2E.

这是简单的例子,但可以使用查询和其他常见的错误的方法发生一样。而且这也会影响像添加,更新,删除通常暴露在库的方法。如果你不写的模拟,这将准确地模拟EF上下文的行为和参照完整性你不会测试您的实现。

This was simple example but same can happen with using methods in queries and other common mistakes. Moreover this also affects methods like Add, Update, Delete usually exposed on repository. If you don't write a mock which will exactly simulate behavior of EF context and referential integrity you will not test your implementation.

故事的另一部分是可以也难以与反对嘲笑单元测试可以检测到延迟加载的问题。

Another part of story are problems with Lazy loading which can also hardly be detected with unit tests against mocks.

正因为如此,你也应该引入积分或终端到终端的测试将使用真实EF背景ANE L2E对真正的数据库。顺便说一句。使用终端到终端的测试是需要正确地使用TDD。在ASP.NET MVC写终端到终端的测试,您可以华廷也可能的 SpecFlow 以BDD但是这将真正增加很多工作,但你有你自己的应用程序真正的考验。如果您想了解更多关于TDD,我建议这本书(唯一的缺点就是例子是在Java中)

Because of that you should also introduce integration or end-to-end tests which will work against real database using real EF context ane L2E. Btw. using end-to-end tests is required to use TDD correctly. For writing end-to-end tests in ASP.NET MVC you can WatiN and possibly also SpecFlow for BDD but this will really add a lot of work but you will have your application really tested. If you want to read more about TDD I recommend this book (the only disadvantage is that examples are in Java).

集成测试意义,如果你不使用通用的存储库,并隐藏在某些类查询,不会暴露的IQueryable 而是直接返回数据。

Integration tests make sense if you don't use generic repository and you hide your queries in some class which will not expose IQueryable but returns directly data.

例如:

public interface IMyEntityRepository
{
    MyEntity GetById(int id);
    MyEntity GetByName(string name); 
}

现在,你可以只写集成测试,测试执行这个仓库,因为查询隐藏在这个类,并没有接触到上层。但是,这种类型的存储库中以某种方式视为与存储过程中使用旧的实现。你会失去很多的ORM这个实现功能或你将不得不做很多额外的工作 - 比如添加规范模式能在上层以限定查询。

Now you can just write integration test to test implementation of this repository because queries are hidden in this class and not exposed to upper layers. But this type of repository is somehow considered as old implementation used with stored procedures. You will lose a lot of ORM features with this implementation or you will have to do a lot of additional work - for example add specification pattern to be able to define query in upper layer.

在ASP.NET MVC可以部分替代控制器级别的终端到终端的测试与集成测试。

In ASP.NET MVC you can partially replace end-to-end tests with integration tests on controller level.

基于评论编辑:

我不说,你需要的单元测试,集成测试和终端到终端的测试。我说,做测试的应用程序需要更多的努力。数量和类型所需的测试依赖于你的应用程序的复杂性,应用的未来预期,你的技能和其他团队成员的技能。

I don't say that you need unit tests, integration tests and end-to-end tests. I say that making tested applications require much more effort. The amount and types of needed tests is dependent on the complexity of your application, expected future of the application, your skills and skills of other team members.

小的简单明了的项目可以在没有在所有测试(好吧,这不是一个好主意,但我们都做到了,在结束它的工作),但一旦项目通过一些treshold你可以找到,引入新的功能或维持创建该项目是非常困难的,因为你永远不会知道,如果它打破一些东西,已经工作 - 这就是所谓的回归。针对回归最好的防守是不错的一套自动化测试。

Small straighforward projects can be created without tests at all (ok, it is not a good idea but we all did it and at the end it worked) but once a project passes some treshold you can find that introducing new features or maintaining the project is very hard because you are never sure if it breaks something which already worked - that is called regression. The best defence against regression is good set of automated tests.


  • 单元测试帮你测试方法。这样的测试应该理想地涵盖了所有的方法执行路径。这些测试应该很短,容易写 - 为复杂的部分可建立依赖关系(mock对象,faktes,存根)。

  • 集成测试帮助你测试翻过多层功能,通常进行的跨多个进程(应用程序,数据库)。你并不需要他们的一切,它更多的是经验,选择他们是有益的。

  • 终端到终端的测试是类似的用例/用户故事/功能验证。它们应该涵盖的要求整个流程。

这是不是需要一个feture多次测试 - 如果你知道了该功能的终端到终端的测试,你不需要写集成测试在同一code测试。此外,如果你知道,方法是通过集成测试你不需要编写单元测试它仅涵盖单一执行路径。这个效果要好得多与在你开始一大考验(端至端或集成)TDD方式和更深入到单元测试。

It is not needed to test a feture multiple times - if you know that the feature is tested in end-to-end test you don't need to write integration test for the same code. Also if you know that method has only single execution path which is covered by integration test you don't need to write unit test for it. This works much better with TDD approach where you start with a big test (end-to-end or integration) and go deeper to unit tests.

根据您的研究与开发方法,你不必启动多种类型,从开始的测试,但你可以在以后介绍他们为你的应用程序将变得更加复杂。唯一的例外是TDD / BDD,你应该开始至少要使用终端到终端的测试和单元测试之前,你甚至写其他code的一行。

Depending on your developement approach you don't have to start with multiple types of test from beginning but you can introduce them later as your application will become more complex. The exception is TDD/BDD where you should start to use at least end-to-end and unit tests before you even write single line of other code.

所以,你问错了问题。现在的问题是不是更简单?现在的问题是怎样才能帮助你在最后什么复杂适合您的应用?如果你想拥有容易单元测试的应用程序和业务逻辑,你应该换EF code到可以嘲笑一些其他类。但在同一时间,你必须引入其他类型的测试,以确保EF code ++工程。

So you are asking the wrong question. The question is not what is simpler? The question is what will help you at the end and what complexity fits your application? If you want to have easily unit tested application and business logic you should wrap EF code to some other classes which can be mocked. But in the same time you must introduce other type of tests to ensure that EF code works.

我不能说你用什么办法将适合您的环境/项目/团队/等,但我可以从我过去的项目解释例如:

I can't say you what approach will fit your environment / project / team / etc. But I can explain example from my past project:

我的工作项目约5-6个月有两个的同事。该项目是基于ASP.NET MVC 2 +的jQuery + EFv4,它是在增量和迭代的方式开发。它有很多复杂的业务逻辑和大量复杂的数据库查询。我们开始与通用的信息库和高code覆盖单元测试+综合测试,以验证映射(插入,删除,更新和选择实体简单的测试)。几个月后,我们发现,我们的做法是行不通的。我们有更多的则1.200的单元测试,code覆盖率约60%(即不是很好)和大量的回归问题。在EF模型改变任何事情都可能引入那些没有触及数周部分意想不到的问题。我们发现,我们缺少集成测试或终端到终端的测试我们的应用程序逻辑。同样的结论在一个平行的团队由工作的另一个项目,并使用集成测试被认为是新项目的建议。

I worked on the project for about 5-6 months with two collegues. The project was based on ASP.NET MVC 2 + jQuery + EFv4 and it was developed in incremental and iterative way. It had a lot of complicated business logic and a lot of complicated database queries. We started with generic repositories and high code coverage with unit tests + integration tests to validate mapping (simple tests for inserting, deleting, updating and selecting entity). After few months we found that our approach doesn't work. We had more then 1.200 unit tests, code coverage about 60% (that is not very good) and a lot of regression problems. Changing anything in EF model could introduce unexpected problems in parts which were not touched for several weeks. We found that we are missing integration tests or end-to-end tests for our application logic. The same conclusion was made on a parallel team worked on another project and using integration tests was considered as recommendation for new projects.

这篇关于ASP.NET MVC3和Entity Framework code第一架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆