I'v e built a basic DAL which can retrieve data and a businesslayer with several objects using this DAL. Once I mapped the data into the business objects and done something with it, I also want to write the data back to the database. Some of the business objects have a lot of properties, so passing every value of a business object as parameter to a method of the corresponding dataservice is not a possibility.
Other ways I've been thinking of:
pass the business object to the the corresponding data service, there execute a SP with all the values as parameters. - sucks, because I have to pass a business object to the DAL (violating the separation) and probably end up with SPs with >50 parameters
create an empty (?) dataset within the business object, fill it with the values from the business object, pass that dataset to the data service and update the db via a dataadapter. I thought of creating an empty dataset with a "... WHERE 0"-SQL String. Would that be a good practice?
This is the first time I do something like this. The latter sounds better to me, but maybe there are other, better approaches? Or The first one is better for some reasons I don't know?
Thank you very much!
[edit:] I can't use LinQ2SQL, cuz I use C# Express (which only supports querying local DBs, while mine is a remote one)
Pass your object into your DAL. If your writting the DAL layer manually your DAL layer should know how to take an Entity and persist it to the DB, and how to return an Entity from the database. The DAL is about persistance of your entities to a non-volatile medium.
You haven't mentioned using LINQ. Is that because you're not using .NET 3.5 yet?
Also, you don't have to make your DAL that generic. The callers of your DAL aren't trying to update all properties of the business object, are they? They probably want to update parts of it, so you should present an API that does this. For instance, they might just want to add an address to a Contact object, or possibly even update a phone number. You need to have a tradeoff between doing what the caller is really trying to do, and the number of separate methods you'd need in order to do that.
The DAL should be all about mapping between your business objects and the specific data representation. This is why the Repository pattern that works with the domain objects, allows you to switch to a different persistance implementation, that might not even be a database.
You are concerned about needing to pass too many parameters to the DAL's methods, and then mention an example where you only need to pass 2 or 3 values. If that is the case, passing it as the method's arguments is reasonable. If you are passing more values, one way you can achieve it is by defining an interface with the subset of values you want to save. This way you are specifying clearly the info that method will be handling.
Regardless of the above, don't make the methods too specific, as you would end up with lots of combinations which can make it harder to mantain.
why do you think that when passing a business object to the DAL you are violating the separation. maybe you should think on separating the bussines objects into another layer.
also you could try linq2SQL in that way you can forget about parameters and this will reduce the number of your SP's.
Unless your Data Access Layer is very generic, how would passing a business object be bad?
I'm a fan of serializing the object and passing the XML to a stored proc, but I'll probably be in the minority.
Related
I'm working on an ASP.NET MVC project in C# with an N-tier architecture.
A class (EmployeeRepo) in the database project has many functions.
Each function's natural result from the transaction is a dataset, but they are converted as per the need.
The return types are:
Dataset (with one or more tables)
DataTable
int
bool
Object (single employee)
List<Object> (list of employees)
Which is better among the two or is there a standard to follow:
Return the result as is without any conversion. The conversion should only happen at other layer and not in the database layer.
It is okay to convert the result in this layer before returning.
Return the result as is without any conversion. The conversion should only happen at other layer and not in > the database layer.
In my view, repository layer should only do one thing. And this thing is to query database without applying any business logic and return result. Why? There are some reasones such as:
it complies with Single Responsibility Principle of SOLID principles.
code becomes simpler
code becomes more reusable
class will have lesser size
easier to write tests
So all conversions are made in service layer.
In addition, it is not good idea to return Dataset (with one or more tables) or DataTable from repository. It is better to return IEnumerable<T>. I mean you should avoid to return IQueryable or DataTable from repository to avoid querying at service layer. There are many opinions about this. So you can choose what is better for you. Should Repositories return IQueryable? imho, repository should not return IQueryable as all query logic should be placed in one place and not scattered across services.
More over, I hihly recommend you to read this post about is it better to return the most specific or most general type from an action method?
Generally speaking, your repository layer will return entities and it is your service layer that will repackage those into a form appropriate for your application to consume.
Note that what constitutes an entity may differ from project to project. For instance, if you use Entity Framework then it uses ADO.NET under the hood but it packages the data into entity classes and returns those objects. You could, in theory, do the same but, if you do, I'd question why you're not already using EF or some other ORM. If you're going to use ADO.NET directly then you probably ought to be returning DataTables and/or DataSets to your service layer. You should certainly not do some of one and some of the other. Go all in with one or the other.
Part of the idea behind a separate repository layer is that multiple different service layers should be able to be laid on top and work seamlessly, so the repository layer should be pretty general, based on the data rather than the application. Conversions are going to require business logic and that belongs in the service layer.
I was debating whether to post this as an answer or vote the question as too opinion-based but I think that the roles of the various layers are well-enough accepted that it's not really opinion any more.
Ideally your repository layer returns data mapped to Domain entitites/Domain types.
So the repository implementation would convert from low level db/ado specific types to your DTOs / Domain Types.
This way, you keep your domain clean and don't let those db specific types trickle into your business domain.
I'm trying to develop a Data Access layer in .NET, C# to be specific, without the use on entity framework, just ADO.NET. In this case the data is coming from a database.
I'd like to keep the data processing logic away from the Data store querying logic. I'm trying to do this to do all my queries via a single method, that takes a SQLCommand, and manages the disposable objects related to the database.
I'd like this method to return the data obtained from the query, I could return the Reader object but that'd imply me having to close and dispose of the reader and it's connection on the caller method, and that's exactly what I'm trying to avoid. The other alternative I've come up with is storing each row in a dictionary where the column name is the key, and returning a list of dictionaries back to the caller, this would allow me to close the connection, but I'm not really sure if this is a good way of accomplishing this. I'd like to know if there is a better (proper?) way of doing this.
The two approaches you have currently are not pretty. The first approach of returning the database reader to the business layer keeps the data layer coupled to the business layer. As an example, think of a day where you decide to use a nosql database, this task would be difficult with the tightly coupled architecture.
The second approach would be difficult to manage.
One approach could be to create repositories on your data layer. For instance, if you have a employee table you could have a employee repository class with methods such as getEmployerById(int id), ect... This repository would return a strongly typed employee (class).
Consuming the employee repo in your business layer would be easy and if the day comes when you wish to switch your data layer to something like nosql then code in the business layer wont care what changes under the getEmployerById method as long as it still functions.
I'm returning DataTable in DAL. And I have a businessObject called Customer. Where should I fill this object? Should it be done in DAL? Or in my front-end app? or where? A little cofused.
If at all possible, you want to avoid returning DataTable in your DAL and instead return the properly filled business object. There are several tools that will help you with this, for example LINQ to SQL, Entity Framework, or (my current favorite) Dapper.NET (used by this very site). I like Dapper best because it's lightweight and works well with a Data Repository pattern, which I frequently use.
You could have a Base DAL, which returns DataTables. Then have an Upper DAL, which does the converting to and from entities, (this is what I tend to use)
You really shouldn't be referring to DataTables in your UI layer.
A half-way house that I have seen before is doing the 'object filling' within a method in the actual business object itself, but that doesn't allow you to switch out your DAL so easily.
When crossing domains like this, where the representation of the data is different in each, you need an integration layer that will take care of the mapping between both representations. Most ORM tools do that mapping for you automatically, though.
But to stick with your example, you could have a layer of mappers to do that. CustomerMapper would then map from the DataTable to the Customer, effectively bridging the two domain representations.
It should be done in BL or Business Logic layer.
I'm working on a small application from scratch and using it to try to teach myself architecture and design concepts. It's a .NET 3.5, WPF application, and I'm using Sql Compact Edition as my data store.
I'm working on the business logic layer, and have just now begun to write the DAL. I'm just using SqlCeComamnds to send over simple queries and SqlCeResultSet to get at the results. I'm starting to design my Insert and Update methods, and here's the issue - I don't know the best way to get the necessary data from the BLL into the DAL. Do I pass in a generic collection? Do I have a massive parameter list with all the data for the database? Do I simply pass in the actual business object (thus tying my DAL to the conrete stuff in the BLL?).
I thought about using interfaces - simply passing IBusinessObjectA into the DAL, which provides the simplicity I'm looking for without tying me TOO tightly to current implementations. What do you guys think?
I don't think there is a simple answer to your questions because there are many options depending on the circumstances. I have found it helpful to read the two books below to help me understand the problems you describe better.
MS .NET: Architecting Applications for the Enterprise (Esposito, Saltarello)
MS Application Architecture Guide, 2nd edition.
The second book is available online. Look here.
I think it is OK to pass the Business object to the Data Access Layer. I think the BLL's job is just to work with its objects, to check if all rules are being followed, about what can be saved, by whom, on what fields, time, etc.
Once it has done that it should pass it to the DAL, and I think it is IT'S job to figure out how to convert what it got into something that can be persisted, but it wont check what is being persisted or read or by whom, it will just do it. This could be straight foward, a la linq, but if your logic mdoels do not match your data model 1:1, then the DAL should do all the conversion.
About tying your DAL to the stuff in the BLL, I think you should worry about the other way around, tying your BLL to your DAL. I would use an interface to represent your DAL (as in IRepository) that way you can make your BLL call any kind of persistance mechanism just by changing the type of IRepository it is using (extra points if you use IoC :P). The concrete classes that implement the IRepository would be tied to the business objects, but they have to know what is it that they are saving don't they? while the BLL does NOT have to know what is doing the saving.
To pass business object in the DAL is the simpler and fastest method. It works in small projects, but have same disadvantages:
1) Business Objects are part of BLL layer, and if you pass objects in BLL then DAL becomes dependent of BLL. low layer knows about upper one - this contradicts the idea of layers at all.
2) Business Object are usially very complex to save it directly in BD. In this case it is better to introduce new "Mappers" intermediate layer.
To overcome all these issues I usially make interface to DAL independent of Business Objects. I use "Row" classes instead - representation of one record in the database or XML. In .NET 3.5 linqtosql autogenerated classes can be used for this purpose.
If I was in your position, I'd probably use LINQ to SQL to define my data access layer - it'll save you lots of work maintaining all that SqlCeFooBar stuff and give you a designer (of sorts) for maintaining your database that you would otherwise lack, using SQL CE.
So in that case, I'd probably couple the business logic layer pretty tightly to the entities exposed by the L2S layer. The justification being that the entities are the business objects, albeit devoid of any services.
I probably wouldn't let the entities get as far up the hierarchy as the UI though. At that level, it makes much more sense to use a model specifically for the view - especially given that you're using WPF.
Of course, all of this depends upon the size and complexity of your application. I'm assuming it's a fairly small scale application (single user?) given that you're using SQL CE.
DTO
I'm building a Web application I would like to scale to many users. Also, I need to expose functionality to trusted third parties via Web Services.
I'm using LLBLGen to generate the data access layer (using SQL Server 2008). The goal is to build a business logic layer that shields the Web App from the details of DAL and, of course, to provide an extra level of validation beyond the DAL. Also, as far as I can tell right now, the Web Service will essentially be a thin wrapper over the BLL.
The DAL, of course, has its own set of entity objects, for instance, CustomerEntity, ProductEntity, and so forth. However, I don't want the presentation layer to have access to these objects directly, as they contain DAL specific methods and the assembly is specific to the DAL and so on. So, the idea is to create Data Transfer Objects (DTO). The idea is that these will be, essentially, plain old C#/.NET objects that have all the fields of, say, a CustomerEntity that are actually the database table Customer but none of the other stuff, except maybe some IsChanged/IsDirty properties. So, there would be CustomerDTO, ProductDTO, etc. I assume these would inherit from a base DTO class. I believe I can generate these with some template for LLBLGen, but I'm not sure about it yet.
So, the idea is that the BLL will expose its functionality by accepting and returning these DTO objects. I think the Web Service will handle converting these objects to XML for the third parties using it, many may not be using .NET (also, some things will be script callable from AJAX calls on the Web App, using JSON).
I'm not sure the best way to design this and exactly how to go forward. Here are some issues:
1) How should this be exposed to the clients (The presentation tier and to the Web Service code)
I was thinking that there would be one public class that has these methods, every call would be be an atomic operation:
InsertDTO, UpdateDTO, DeleteDTO, GetProducts, GetProductByCustomer, and so forth ...
Then the clients would just call these methods and pass in the appropriate arguments, typically a DTO.
Is this a good, workable approach?
2) What to return from these methods? Obviously, the Get/Fetch sort of methods will return DTO. But what about Inserts? Part of the signature could be:
InsertDTO(DTO dto)
However, when inserting what should be returned? I want to be notified of errors. However, I use autoincrementing primary keys for some tables (However, a few tables have natural keys, particularly many-to-many ones).
One option I thought about was a Result class:
class Result
{
public Exception Error {get; set;}
public DTO AffectedObject {get; set;}
}
So, on an insert, the DTO would get its get ID (like CustomerDTO.CustomerID) property set and then put in this result object. The client will know if there is an error if Result.Error != null and then it would know the ID from the Result.AffectedObject property.
Is this a good approach? One problem is that it seems like it is passing a lot of data back and forth that is redundant (when it's just the ID). I don't think adding a "int NewID" property would be clean because some inserts will not have a autoincrementing key like that. Another issue is that I don't think Web Services would handle this well? I believe they would just return the base DTO for AffectedObject in the Result class, rather than the derived DTO. I suppose I could solve this by having a LOT of the different kinds of Result objects (maybe derived from a base Result and inherit the Error property) but that doesn't seem very clean.
All right, I hope this isn't too wordy but I want to be clear.
1: That is a pretty standard approach, that lends itself well to a "repository" implementation for the best unit-testable approach.
2: Exceptions (which should be declared as "faults" on the WCF boundary, btw) will get raised automatically. You don't need to handle that directly. For data - there are three common approaches:
use ref on the contract (not very pretty)
return the (updated) object - i.e. public DTO SomeOperation(DTO item);
return just the updated identity information (primary-key / timestamp / etc)
One thing about all of these is that it doesn't necessitate a different type per operation (contrast your Result class, which would need to be duplicated per DTO).
Q1: You can think of your WCF Data Contract composite types as DTOs to solve this problem. This way your UI layer only has access to the DataContract's DataMember properties. Your atomic operations would be the methods exposed by your WCF Interface.
Q2: Configure your Response data contracts to return a new custom type with your primary keys etc... WCF can also be configured to bubble exceptions back to the UI.