Question

I am working on a project using 3 tier architecture. I want to knw about how to pass datareader value from DAL to Presentation layer

My code is like this. In DAL layer

public class HomeDAL
{
 public SqlDataReader DefaultSearchFriends(long userid)
 {
    SqlConnection SocialConn = new SqlConnection(connstr);

    using (SqlCommand comm = new SqlCommand("proc_FriendsSearch", SocialConn))
    {
        comm.CommandType = CommandType.StoredProcedure;
        comm.Parameters.AddWithValue("@userid", userid);
        SocialConn.Open();
        SqlDataReader dr = comm.ExecuteReader(CommandBehavior.CloseConnection);
        return dr;
    }
 }
}

In BAL layer

public class HomeBAL
{
    public SqlDataReader DefaultSearchFriends(long userid)
    {
       HomeDAL HDAL = new HomeDAL();
       SqlDataReader dr = HDAL.DefaultSearchFriends(userid);
       return dr;
    }
}

On Presentaion Layer I wrote this on Page load

HomeBAL HBAL = new HomeBAL();
SqlDataReader dr = HBAL.DefaultSearchFriends(user_id);
while (dr.Read())
{ 
 //some code
}

Now i want to know two things

1- Is this right to call datareader in this way or there is some better logic.

2- how to close datareader object in BAL layer and in DAL layer.

Was it helpful?

Solution

Well, the basic idea of a layered architecture is to decouple the different components for several reasons. Some reasons are testability, maintainability, extensibility but there are many more.

To pass the data between these layers - well it depends a bit on the kind of data - but usually you would use some simple classes as data transfer objects (DTO), which would be filled with data in the DAL. E.g.

public class Person
{
  public string Name {get; set;}
  public string FirstName {get; set;}
  ...
}

With your approach you are breaking this idea, because you're passing the DataReader to presentation layer which implies, that you cannot switch the DAL technology without touching the other layers. E.g. if you want to use Entity Framework you would have to modify every part in the code, where you're currently using the SqlDataReader.

You can also see, if you'd stick to the idea behind the layered approach, you don't have to think about your second question.

I hope this helps a little bit.

EDIT

Ok I'm a bit curious, that you don't find a proper solution. But anyways, the first and simplest approach could be, don't publish the SqlDataReader. Handle its life cycle in the DAL. Means, assuming that you're using my DTO above

public class HomeDAL
{
 public List<Person> DefaultSearchFriends(long userid)
 {
    SqlConnection SocialConn = new SqlConnection(connstr);

    using (SqlCommand comm = new SqlCommand("proc_FriendsSearch", SocialConn))
    {
        comm.CommandType = CommandType.StoredProcedure;
        comm.Parameters.AddWithValue("@userid", userid);
        SocialConn.Open();
        SqlDataReader dr = comm.ExecuteReader(CommandBehavior.CloseConnection);

        var persons = new List<Person>();

        while (dr.Read())
          persons.Add(new Person { Name = dr["Name"], FirstName = dr["FirstName"] });

        dr.Close();

        return persons;
    }
 }
}

would be the much better approach.

OTHER TIPS

I think your architecture has problems;

  1. you are using concrete classes to query database; instead you need an abstraction in case you change the backend SQL server or the querying mechanism.

  2. you are passing concrete SqlDataReader into all of your layers. From DAL, you need to return data objects not the db operation context instance.

  3. you need to change only domain objects between layers, not the object doing the actual work.

I suggest you to refer to n layer reference application of microsoft spain

IN DAL File

public class HomeDAL
{
  public void DefaultSearchFriends(ref HomeBAL hBAL)
  {
    SqlConnection SocialConn = new SqlConnection(connstr);
    using (SqlCommand comm = new SqlCommand("proc_FriendsSearch", SocialConn))
    {
        comm.CommandType = CommandType.StoredProcedure;
        comm.Parameters.AddWithValue("@userid", hBAL.userid);
        SocialConn.Open();
        hBAL.Search_Reader = comm.ExecuteReader(CommandBehavior.CloseConnection);
    }
  }
}

In BAL File

public class HomeBAL
{
public SqlDataReader Search_Reader = null;
}

and in Presentaion layer

 HomeBAL HBAL = new HomeBAL();
HomeDAL HDAL = new HomeDAL();
HDAL.DefaultSearchFriends(ref HBAL);
SqlDataReader dr = HBAL.Search_Reader;    
while (dr.Read())
{
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top