Link to home
Start Free TrialLog in
Avatar of Priest04
Priest04Flag for Serbia

asked on

3-tiered application - layer dependency

this question is related to 3-ties application design only, not 4+ tiered.

DAL
BLL
UI

UI form - displays collection of clients info (this is the example I would like use as reference)

I am interested in how would what layer pass data up to the UI form? The important thing is that layer dependency cannot be mutual, meaning all three layers reside in a separate dll (exe). So no need for coding properties, methods, etc, I just need interfaces to see how would data flow.
SOLUTION
Avatar of sunnycoder
sunnycoder
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Priest04

ASKER

This is not the answer I was looking for. I know what is the purpose of those 3 layers, but when we talk about DAL and BLL, how would DAL pass data from database to DLL. An example of interface for a DAL class and for BLL class, regarding loading customers, would be great.

I am not interested in using DataSets, DataAdapters etc, I want to use custom entities.
Hi,

You can get the data from the database any way you want.

Some people use Stored procedures in order to retrieve data via a dataset and then populate their custom (customer) classes by iterating through each record and creating a List<Customer> of their custom object and returning that. Others use LINQ to SQL as a way to retrieve the data and then iterate through this collection and populate their custom objects. You could also use ADO.NET Entities which is another way to get data from the database and populate custom objects at the same time. Another option is to buy a ORM tool.

http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx

http://msdn.microsoft.com/en-us/library/aa697428(VS.80).aspx

The business layer will then use your custom objects in order to fulfill some business logic (whatever that may be).

Darren


         public interface IDatabase
	{
 
		// Used when calling stored procedures and returning scalar values.
		DataSet ExecuteSPQuery(string sConnection, string sStoredProcName) ;
		int ExecuteSPNonQuery(string sConnection, string sStoredProcName) ;
		string ExecuteSPScalar(string sConnection, string sStoredProcName) ;
 
		// Parameter overloaded methods.
		void AddParameter(string sParamName, SqlDbType EnumDBType, int iStrLen, string sValue) ;
		void AddParameter(string sParamName, SqlDbType EnumDBType, int iStrLen, byte[] sValue) ;
		void AddParameter(string sParamName, SqlDbType EnumDBType, long lValue) ;
 
		// Methods to add return and output parameters and retrieve their values.
		void AddOutputParameter(string sParamName, SqlDbType EnumDBType, int iStrLen) ;
		object GetOutputParameter(string sParamName) ;
 
		int Timeout{ get; set; }
	}

Open in new window

Ok, seems you do not undertstand me. I have DAL class ready for getting data FROM database. I will post bellow how it looks like. The question I am asking is related to passing data that is taken from database TO business layer - how? What is the best pattern to do this? And a basic example of interface related to customers would be great.

This is how methods for getting data from database look like

int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params IDataParameter[] commandParameters);
int ExecuteNonQuery(CommandType commandType, string commandText, params IDataParameter[] commandParameters);
int ExecuteNonQuery(IDbTransaction trans, CommandType commandType, string commandText, params IDataParameter[] commandParameters);
 
IDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText, params IDataParameter[] commandParameters);
IDataReader ExecuteReader(CommandType commandType, string commandText, params IDataParameter[] commandParameters);
 
object ExecuteScalar(string connectionString, CommandType commandType, string commandText, params IDataParameter[] commandParameters);
object ExecuteScalar(CommandType commandType, string commandText, params IDataParameter[] commandParameters);
object ExecuteScalar(IDbTransaction trans, CommandType commandType, string commandText, params IDataParameter[] commandParameters);
 
IDataParameter CreateParameter(string paramName, System.Data.DbType paramType, object paramValue);

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I really don't understand the problem: it's the DAL duty to retrieve database information and create an object that BLL can cruch.
Now, creating that object is a very technical specific matter. I know how to do it in Java because I personally studied JDBC type 2 connector. The DAL retrieves the aswer string to the query and parses the attributes to build a bean. In Java is something like what i attached
If you have this type of things you are done.
Did I answer?
String retrieve = "select * from pdoducts where id=?";
statement = connection.prepareStatement(retrieve);
statement.setInt(1, id);
ResultSet result = statement.executeQuery();
if (result.next()) {
prodotto = new Product();
prodotto.setCode(result.getString("code"));
prodotto.setName(result.getString("name"));
prodotto.setDescription(result.getString("description"));
prodotto.setAvailability(result.getInt("availability"));
prodotto.setPrice(result.getInt("price"));
prodotto.setId(id);
}

Open in new window

Thanks for the response, guys.

@Votech

I will look at the code you have provided and will let you know if this is what I wanted.

@ai_ja_nai

The problem is I dont understand the approach with 3 layered model. Here in your example you use Product class. Where is the Product class defined? If in BLL, then DAL will need a reference to BLL in order to use Product class. If this is true, then BLL CANNOT reference DAL, because circular dependency is not allowed. And then how would BLL receive data from DAL?

ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
To further explain, the user press a button on the web page, asking to modify a price.
The ui dispatches a request to the business logic, which has a method to modify the 'price' attribute of a product. This method accept as input paramenter a product object and the new price.Since this object is not already there, it automatically triggers a request of creating the object. This dispatches a request to a method belonging to the DAL, which retrieves the informatios from the db and assembles a bean, returned by the just invoked method.
Then, this bean is processed by the modify_price method, which at the end calls for a store_modifications methods, which takes as input a product bean. This executes an update on db table and stores the new informations. The control return to BLL, that in turn passes it to the UI, which writes on the screen "operation done".
Now, the product bean is still there, until the garbage collection will decide it can be killed, waiting for new operations to be done on it.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I do not understand this part:

>>But a tier is not something that has to be phisucally separeted. Of course, everything will be in its own packages, but everybody >>can access to everything.

This I cannot manage to make it work. When I keep all 3 layes in different projects, I cannot find way to reference them.

>>Now, a good idea is to create a common facade of callable methods to allow interoperativity.
>>When needed, the program will call for a method which returns an instatiated object, available to all the application environment >>(call to DAL) and throwable either to the presentation layer (call for UI) or to a "modify price" operation (call for BLL). it depends >>on who called the create method.

I also dont know how to implement that in practice. Here is a real example: I create one project called DAL, and in there, beside having a class that I mentioned before (that executes statements on database), which I will call SqlHelper.  I also have one class called ProductInfo, which, to my thinking should contain next methods

class ProductInfo
{
    public Product GetProduct(int productID)  {....}
    public IList<Product> GetProducts()  {....}
    public int SaveProduct(int productID)  {....}
    public int SaveProducts()  {....}
    public int DeleteProduct(int productID)  {....} // this one maybe doesnt need to exist, maybe it should be handled by SaveProducts

}

thic class uses SqlHelper class to do CRUD operations. I compile this dll into DAL.dll. As it can be seen, DAL uses Product class, which is defined in BLL.dll. So it needs reference to BLL.dll.

Next I have one project called BLL. It has Product class which you have defined in your last post. Can you post the interfaces that will be needed in BLL to get data from database through DAL.dll. I cannot reference DAL.dll, IDE doesnt allow me to - I get circular dependency is not allowed exception.
Hello Darren,

to simlify thigs, we will talk here about logical separation only. When I speak of 3 laters, that would mean UI (app,exe), BLL (bll.dll) and DAL (dal.dll). So, if I understood you completely. you say that it is "not possible" to have 3 layers, but we need a 4th dll, so BLL and DAL should reference to this 4th dell. If this is correct, then this is how I do my applications now, but I thought of maybe I am doing something wroing, and maybe there isnt need for the 4th layer. If you look at this example, MS talks about 3 layered approach. When I said "not possible", I meant in a feasable  way, since you can always use arrays to pass thata from DAL to BLL, but that would again mean a 4th layer, since here we are using mscorlib.dll (array class).

http://msdn.microsoft.com/en-us/library/ms978689.aspx
Ok, ProductInfo is your facade of DAL functions. Everytime you need something that has to do with persistence layer, you ask for this.

Now, the application BLL must be aware of  the ProductInfo class, to call its methods, which call at their own turn the CRUD methods. Or, at least, must import the DAL methods to contact the db in some way.

I see that your IDE doesn't allow you due to circular dependencies. I belive that there is a design mistake, because it's a vertical dependency, it cannot be circular. BLL asks operations to DAL, which return something useful to BLL. Stop. DAL of course must import the Product class to build a product object, but it never relies on BLL operations.
So, what can I do about it?

>> BLL asks operations to DAL, which return something useful to BLL.

this means that BLL needs reference to dal.dll

>> DAL of course must import the Product class to build a product object, but it never relies on BLL operations.

this means that DAL needs reference to bll.dll. which is not possible to achieve.

That was my primary question. :)

If you believe its a design mistake, I would then need information how to redisgn it, but without importing 4th layer. Is this possible or not? According to headline from MS link I posted above, its possible.
The mistake was to build definitions of domain objects, shared by everybody, inside a layer. I never said that being used by a layer they should be part of the latter. Of course, now there is a circular dependency.
You should put those definitions aside, in an own dll. Or, if you HAVE to put them into a layer, put them into DAL.dll, so DAL may use it because is built in and BLL inherits it on the import.
By the way, a layer doesn't have to be a unique file. Most of times, it's a folder or an archive with many files inside. That folder/archive is called a package and is the best way to organize the components