不使用数据集的 N 层架构(数据集听起来对性能很不利)
我阅读了有关 n 层架构的书籍、文章、教程以及所有此类内容,并且我正在尝试应用著名的 3 层(DAL、BLL、PL)。我刚刚进入游戏,实际上,我已经阅读了很多有关将整个数据库加载到内存中(数据集所做的)有多么糟糕的文章,尤其是当我需要查看某个项目的详细信息时,这将不得不从 5 个表或其他东西中检索,所以会很多,而且我只想要一条记录!这是我需要很多记录的唯一情况,一次不会太多,它将检索非常简单的信息(id、姓名、地址),如下所示!
您认为找到另一种方法来创建没有数据集的 DAL 和 BLL 更好吗?还是数据集更好?如果数据集对性能等不利,您有任何材料可以教我如何做到这一点吗?
I read books, articles, tutorials, and all that kind of stuff about the n-tier architecture, and I'm trying to apply the famous 3-tier (DAL, BLL, PL). I just got into the game, actually, I've read a lot about how bad is to load the whole database into memory (which the dataset do) especially when I'm going to need to view details about an item which will have to be retrieved from 5 tables or something, so it will be a lot and I want just ONE RECORD! and the only case where I'll need many records It won't be much at a time and it will retrieve very simple information (id, name, address) something like this!
Do you think it's better to find another way to create my DAL and BLL without datasets? or dataset is better? if the dataset is not good for performance and so on, do you have any material to teach me how to do so?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
大多数所说的都是中肯的建议。我同意,如果您打算投入时间来构建 N 层应用程序,那么您应该考虑考虑 ORM 解决方案。如果您正在基于 .NET 技术进行构建,那么 EF4 是构建 DAL 的一种非常好的方法。
您对 DAL/BLL 应该返回的内容的理解肯定存在混乱。数据集现在在 .NET 3 和 4 中有点过时,尽管并不罕见。在构建 DAL 时,您应该阅读存储库设计模式。根据实现的不同,您的存储库通常会返回一个通用的
List。或 IQueryable
。 IQueryable 是我的偏好,但是,有人认为它模糊了 BLL 和 DAL 之间的界限。一些实现还要求每个聚合都有自己的存储库。 (即 CustomerRepository、EmployeeRepository)我发现创建一个类型有约束的通用存储库是最简单也是最好的方法。
例如:
Repository: IRepository;其中 TEntity : ITrackable
要了解设计 DAL 的好方法,请查看 nCommon。
Tony Sneed 有一个关于将实体框架与 POCO 结合使用的精彩博客系列:
http ://blog.tonysneed.com/2010/02/19/trackable-dtos-take-n-tier-a-step-further-with-ef4/
设计 DAL 和域层所花费的时间至关重要。
我的建议是主观的,不应被视为正确或错误。不知道你的申请要求。如果您可以使用简单的数据集和 sqldatareaders 更快地编写一些代码,那么您的投资回报可能会更大。如果您希望构建可维护的设计,请像其他人建议的那样,花额外的时间阅读 EF4 和 N 层架构模式。
[编辑]
为了回应您下面的评论,我想我可以分享一些我在学习建筑时发现的宝贵资源。
首先,准备好投入无数个小时的阅读和重读。利用您当前的知识并不断练习,应用您所学到的知识。最重要的是要认识到:你的设计永远不会是完美的,因为不存在这样的事情,并且仅仅因为你应用了一种模式并不一定会使其成为最好的。
拥有自己的个人项目对于在 OOP 领域取得进步是非常宝贵的。在马尔科姆·格拉德威尔 (Malcolm Gladwell) 的《异常值》一书中,他提出理论,平均需要 10,000 小时的练习才能掌握某件事。因此,继续编码和学习。 :)
您可以选择的最好的书籍之一是 Head First - 设计模式。它被高度评价为一本出色的 OOD 入门书籍,并且改变了您对代码的思考方式。我记得读完几章后立即意识到,“哇!我一直在编写这样的代码,但从来不知道它有名字!”它帮助我意识到设计问题是多么熟悉;他们有通用的解决方案,以及能够与其他开发人员沟通这些解决方案是多么重要。那本书会严重地打击你的屁股(以一种好的方式)。
但请注意,架构和设计书籍将为您提供设计应用的场景以及模式的实现。我花了一段时间才意识到可以有很多方法来实现该模式……尤其是在 .NET 中。当您开始阅读 Martin Fowler、Robert C. Martin、Eric Evans、Dino Esposito 的书籍时,您就会发现这一点。
有许多优秀的免费在线资源,例如 Microsoft 的应用程序架构指南。学习技术的一些最佳方法就是阅读博客。
对于实体框架,很难击败 Julia Lerman 的编程 EF4。至于阐明 ORM 的作用 - 它促进与数据库的通信,并允许您像面向对象一样“查询”它。例如一些伪代码:
查询
使用 SqlDataReader,您通常会运行类似
"SELECT * FROM Users WHERE Users.UserId = 1"
的使用 ORM,您实际上并没有编写 SQL。 ORM 将数据库表映射到实际的类对象,从而允许您查询强类型对象。因此,您可以编写如下内容:
User user = EFContext.Users.Where(u => u.UserId == 1).SingleOrDefault();
ORM 负责将其转换为 SQL 并执行查询。这种抽象还允许 ORM 通过提供程序可扩展性与多个数据库(MSSQL、Oracle、MySql)配合使用。
当您开始涉及分层架构时,您的 存储库 负责与 ORM 或数据库进行通信并返回您的结果发送至您的 BLL。例如,一个基本示例如下所示:
using (varrepository = new Repository())
{
用户 user = repository.Where(u => u.UserId == 1).SingleOrDefault();
这
是 ORM 及其使用方式的非常基本的定义。一旦你开始学习模式:如何识别它们,何时使用它们(并非总是如此,因为它们可能会使简单的事情变得过于复杂)并重构你自己的代码,然后开始阅读领域驱动设计。
希望这有帮助。
[编辑2]
当然,让我澄清一下每层实际返回的内容。根据您的存储库实现和设计决策:
从 ORM 所在的基础设施层,您通常会返回通用
List
或>IQueryable
其中T
代表您的对象。实体对象还是 POCO 由您决定。 POCO 只是一个代表数据的类,但它不仅仅是一组 getter 和 setter。它至少应该包含验证。阅读贫血领域模型以及如何避免它们。从包含业务逻辑的域层,根据您尝试实现的松散耦合程度,您可以返回
List
、BindingList
,或者您将使用映射技术将 DTO 集合返回到表示层和服务层。DTO 增加了另一系列的复杂性,但对于某些场景来说是必不可少的。 DTO 是不可变的对象。它们应该这样构建:
它们只是的 getter 和 setter 包。您的 POCO 应该能够轻松映射到它们,并且有一个出色的软件可以使此过程变得简单:AutoMapper。它们不必代表数据库或 POCO 对象中的精确表,但可以包含其中的多个部分,如上所示。
有一个问题。有时,DTO 的信息不足以返回到您的服务或 Web UI。您通常还需要返回验证结果、错误处理信息,可能还需要返回一个布尔值来表示事务的结果。
该对象没有确切的名称,但我将其称为响应传输对象,它由
List
、来自 Microsoft 企业库的 ValidationResults 以及我需要的任何其他内容组成知道。这需要消耗大量信息。在学习 NLayer 开发时,像分解每一层一样将其分解。一次学习一件事,写下你脑海中出现的每个问题。请务必寻找这些答案。
Most of what's been said is solid advice. I would agree that if you're looking into investing the time to build an N-Tier application, you should consider looking into an ORM solution. If you're building on .NET technologies, EF4 is a very good approach to building your DAL.
There is definite confusion on your understanding of what your DAL/BLL should be returning. DataSets are a bit antiquated now in .NET 3 and 4, though not uncommon. You should read up on the Repository design pattern when building your DAL. Depending on the implementation, your repository will typically return a generic
List<T> or IQueryable<T>
. IQueryable is my preference, however, it's been argued that it blurs the lines between your BLL and DAL.Some implementations also call for every aggregate to have its own repository. (ie CustomerRepository, EmployeeRepository) I've found it simplest and best to create a generic Repository where the type has a constraint.
So for example:
Repository<TEntity> : IRepository<TEntity> where TEntity : ITrackable
To see an great approach to designing your DAL, take a look at nCommon.
Tony Sneed has an excellent blog series on using Entity Framework with POCOs:
http://blog.tonysneed.com/2010/02/19/trackable-dtos-taking-n-tier-a-step-further-with-ef4/
The time spent designing your DAL and Domain layer is critical.
My advice is subjective and shouldn't be taken as correct or incorrect. I don't know the requirements of your application. The return on investment might be greater for you if you can hammer out some code quicker with simple datasets and sqldatareaders. If you're looking to build a maintainable design, spend the extra time reading about EF4 and N-Layer architecture patterns like the others have suggested.
[EDIT]
In response to your comment below I thought I could share some valuable resources I've found in learning architecture.
First off be prepared to put in countless hours of reading and re-reading. Using your current knowledge and with constant practice, applying what you learn. The most important thing to realize is: your design will never be perfect because there's no such thing, and just because you apply a pattern does not necessarily make it best.
Having your own personal projects is invaluable to moving forward in OOP. In Malcolm Gladwell's book Outliers, he theorizes that it takes an average 10,000 hrs of practice before you can master something. So keep coding and learning. :)
One of the best books you can pick up is Head First - Design Patterns. It's highly regarded as a phenomenal introductory book to OOD and changes the way you think about code. I remember reading through several chapters and instantly realizing, "Wow! I've been writing code like this all along, but never knew there were names for it!" It helped me realize how familiar design problems are; that there are common solutions for them, and how important it is to be able to communicate them with fellow developers. That book will seriously knock you on your ass (in a good way).
Note, however, that architecture and design books will give you a scenario in which the design applies as well as an implementation of the pattern. It took me a little while to realize there can be many ways to implement the pattern ... especially in .NET. You'll see that when you start reading books by Martin Fowler, Robert C. Martin, Eric Evans, Dino Esposito.
There are many excellent resources for free online such as Microsoft's Application Architecture Guide. Some of the best ways of learning techniques are simply reading blogs.
For Entity Framework, it's hard to beat Julia Lerman's Programming EF4. As to clarify the role of an ORM - it facilitates communication with your database and allows you to "query" it as if it were object oriented. So for example some pseudocode:
With a SqlDataReader, you would normally run a query like
"SELECT * FROM Users WHERE Users.UserId = 1"
With an ORM, you're not actually writing the SQL. The ORM maps your database tables to actual class objects, thus allowing you to query against a strongly typed object. So you would write something like:
User user = EFContext.Users.Where(u => u.UserId == 1).SingleOrDefault();
The ORM is responsible for translating this into SQL and executing the query. This abstraction also allows the ORM to work with multiple databases (MSSQL, Oracle, MySql) through provider extensibility.
When you start involving a layered architecture, your Repository is responsible for communicating with the ORM or database and returning your results to your BLL. For instance a basic example would look something like:
using (var repository = new Repository<User>())
{
User user = repository.Where(u => u.UserId == 1).SingleOrDefault();
}
This is a very rudimentary definition of an ORM and how it's used. Once you start learning patterns: how to recognize them, when to use them (not always, as they can over complicate something simple) and refactor your own code, then start reading into domain-driven design.
Hope this helps.
[EDIT 2]
Sure, let me clear up what's actually being returned by each layer. Depending upon your repository implementation and your design decisions:
From your Infrastructure layer which is where the ORM sits, you would typically return either a generic
List<T>
or anIQueryable<T>
whereT
represents your object. Whether its an Entity Object or POCO is up to you. A POCO is simply a class that represents your data, however it's not just bags of getters and setters. It should contain validation at least. Read up on anemic domain models and how to avoid them.From your Domain layer, which contains your business logic, depending on how loose coupling you're trying to achieve, you'd either return a
List<T>
,BindingList<T>
, or you will use a mapping technique of returning a collection of DTOs to your presentation and service layers.DTOs add another series of complications, but are essential to some scenarios. DTOs are immutable objects. They should be built like such:
They are only bags of getters and setters. Your POCOs should be able to easily map to them and there's an excellent piece of software to make this process simple: AutoMapper. They do not have to represent exact tables in your database or or POCO objects, but can comprise several parts of them like seen above.
There is one catch. Sometimes DTO's are not enough information to return to your services or web UI. You'd also typically need to return validation results, error handling information, maybe a boolean to express the result of the transaction.
There's not an exact name for this object, but I've gone on to call it a Response Transfer Object which composes a
List<IDto>
, ValidationResults from Microsoft's enterprise library, and anything else I would need to know.This a lot of information to consume. When learning NLayer development, break it up as you would each layer. Tackle learning one thing at a time and write down every question that pops into your head. Make sure to seek out those answers.
这听起来很适合 LINQ to SQL。它为您提供所需的性能,并配有非常简单的强类型访问数据的方式。
This sounds like a good candidate for LINQ to SQL. It give you the performance you're looking for, paired with a very simple strongly-typed way to access your data.
我很少使用数据集。但是,我认为你对他们有一个错误的印象。
数据集不包含整个数据库...除非您通过
Command
和Adapter
运行的查询返回整个数据库。如果您想要的只是少量行,则仅查询该行,这就是数据集将包含的全部内容。如果您能够使用 NHibernate、Linq to SQL 或 Entity Framework 之类的工具,那么这可能是您的一个好方法;它为您提供了 ADO.NET 数据集的一些离线优势,而无需承担所有开销。
I very rarely use Datasets at all. But, I think you are under a mistaken impression about them.
Datasets do not contain the whole database... unless the query you run through the
Command
andAdapter
returns the whole database. If all you want is a small number of rows, then query only that, and that's all the Dataset will contain.If you are able to use something like NHibernate, Linq to SQL or Entity Framework though, that might be a good way to go for you; It gives you some of the disconnected benefits of ADO.NET datasets without, necessarily, all of the overhead.
我认为你应该抽象每一层。您最终应该决定使用哪个数据库。设计和实现一切,以便您基本上可以插入您想要的任何数据存储,您不希望数据库规定您的解决方案的任何要求。
我推荐你读很多关于设计模式的书,其中一本是四人帮的书。
I think you should abstract each layer. Which database you're using is something you should decide in the end. Design and implement everything so you can jack in basically any data storage you want, you don't want the database to dictate any requirements on your solution.
There is a lot of books about design patterns that I recommend you to read, one of them is the one by the gang of four.
如果您只需要 1 条记录,您不想查询数据库并返回 1,000 条记录。当您查询数据库并且只需要一条记录时,请编写 SQL 以仅定位您需要的记录。
我已经研究 .Net 很长时间了,如果我是你,我会花一些时间研究实体框架、实体空间(我的偏好)、nHibernate 或某种时尚的 ORM。
它们使生活变得更加轻松,如果做得正确,您仍然可以拥有良好的松散耦合架构。
简而言之,数据集相当蹩脚,它们看起来很强大,但通常会导致架构很差。
You don't want to query your database and return 1,000's of records if you only need 1. When you query your DB and only want one record then write your SQL to target just the records you need.
I've been doing .Net for a long time, if I were you I would take some time and look at Entity Framework, Entity Spaces (my preference), nHibernate or an ORM of some fashion.
They make life much easier, and if done correctly you can still have a good loosely coupled architecture.
In short, datasets are pretty lame and they seem all powerful but usually make for a poor architecture.