Reputation: 3499
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?
Upvotes: 3
Views: 2286
Reputation: 1883
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 an IQueryable<T>
where T
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:
[DataContract]
public sealed class UserSummary : IDto
{
[DataMember]
public String FirstName { get; private set; }
[DataMember]
public String LastName { get; private set; }
[DataMember]
public UserProfile Profile { get; private set; }
public UserSummary(String firstName, String lastName, UserProfile profile)
{
FirstName = firstName;
LastName = lastName;
Profile = profile;
}
}
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.
Upvotes: 5
Reputation: 2391
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.
Upvotes: 0
Reputation: 23472
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.
Upvotes: 0
Reputation: 40150
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
and Adapter
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.
Upvotes: 0
Reputation: 26863
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.
Upvotes: 1