C# 如何将datareader值从DAL传递到表示层

C# 如何将datareader值从DAL传递到表示层,c#,asp.net,3-tier,C#,Asp.net,3 Tier,我正在从事一个使用三层体系结构的项目。 我想了解一下如何将datareader值从DAL传递到表示层 我的代码是这样的。 在DAL层中 public class HomeDAL { public SqlDataReader DefaultSearchFriends(long userid) { SqlConnection SocialConn = new SqlConnection(connstr); using (SqlCommand comm = new SqlComm

我正在从事一个使用三层体系结构的项目。 我想了解一下如何将datareader值从DAL传递到表示层

我的代码是这样的。 在DAL层中

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;
    }
 }
}
在BAL层中

public class HomeBAL
{
    public SqlDataReader DefaultSearchFriends(long userid)
    {
       HomeDAL HDAL = new HomeDAL();
       SqlDataReader dr = HDAL.DefaultSearchFriends(userid);
       return dr;
    }
}
在呈现层,我在页面加载时写了这个

HomeBAL HBAL = new HomeBAL();
SqlDataReader dr = HBAL.DefaultSearchFriends(user_id);
while (dr.Read())
{ 
 //some code
}
现在我想知道两件事

1-以这种方式调用datareader是正确的还是有更好的逻辑


2-如何关闭BAL层和DAL层中的datareader对象。

我认为您的体系结构存在问题

  • 您正在使用具体的类来查询数据库;相反,您需要一个抽象,以防更改后端SQL server或查询机制

  • 您正在将concrete
    SqlDataReader
    传递到所有层中。从DAL中,您需要返回数据对象,而不是db操作上下文实例

  • 您只需要在层之间更改域对象,而不需要更改执行实际工作的对象


  • 我建议您参考

    好吧,分层体系结构的基本思想是将不同的组件解耦,原因有几个。 一些原因是可测试性、可维护性和可扩展性,但还有很多其他原因

    要在这些层之间传递数据——这有点取决于数据的类型——但通常您会使用一些简单的类作为数据传输对象(DTO),在DAL中填充数据。例如

    public class Person
    {
      public string Name {get; set;}
      public string FirstName {get; set;}
      ...
    }
    
    您的方法打破了这个想法,因为您将
    DataReader
    传递给表示层,这意味着您无法在不接触其他层的情况下切换DAL技术。例如,如果您想使用实体框架,您必须修改代码中的每个部分,您当前使用的是
    SqlDataReader

    你也可以看到,如果你坚持分层方法背后的想法,你不必考虑第二个问题

    我希望这有点帮助

    编辑

    好吧,我有点好奇,你没有找到合适的解决办法。但是无论如何,第一个也是最简单的方法可能是,不要发布
    SqlDataReader
    。在DAL中处理其生命周期。也就是说,假设你用的是我上面的DTO

    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;
        }
     }
    }
    公共类HomeDAL
    {
    公共列表DefaultSearchFriends(长用户ID)
    {
    SqlConnection-SocialConn=新的SqlConnection(connstr);
    使用(SqlCommand comm=newsqlcommand(“proc_FriendsSearch”,SocialConn))
    {
    comm.CommandType=CommandType.StoredProcess;
    comm.Parameters.AddWithValue(“@userid”,userid);
    SocialConn.Open();
    SqlDataReader dr=comm.ExecuteReader(CommandBehavior.CloseConnection);
    var persons=新列表();
    while(dr.Read())
    添加(新人物{Name=dr[“Name”],FirstName=dr[“FirstName”]});
    Close博士();
    返回人员;
    }
    }
    }
    将是更好的方法。

    在DAL文件中

    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);
        }
      }
    }
    
    在BAL文件中

    public class HomeBAL
    {
    public SqlDataReader Search_Reader = null;
    }
    
    在呈现层

     HomeBAL HBAL = new HomeBAL();
    HomeDAL HDAL = new HomeDAL();
    HDAL.DefaultSearchFriends(ref HBAL);
    SqlDataReader dr = HBAL.Search_Reader;    
    while (dr.Read())
    {
    }
    

    谢谢,先生,你能给我举个好例子解释一下吗。如果你参考我提供的链接,这里有详细的解释。这里要解释的时间太长了(有很多概念,你需要根据你的需要决定使用还是不使用)。谢谢你,伙计,我知道我的体系结构包含问题。但现在我想纠正这些错误。请在我向您展示代码的同时向我展示解决方案。在DAL和BLL文件中要做什么。谢谢你,伙计,但是你现在能给我一个正确的解决方案吗?如何使用sqldatareader。我向你展示我的架构,我知道它有问题。但现在我该如何纠正这些错误呢。请在我向您展示代码的同时向我展示解决方案。DAL和BLL中要做什么file@ankitGupta:我不确定,为什么在我们的解释之后你看不到解决方案,但是请看我的编辑。@ankitGupta:如果它对你有效,那么它没有错。但是考虑到分层体系结构,这是完全错误的,因为您没有分离任何东西。正如我在上面的文章中所描述的,DAL唯一应该发布的是通过DTO的数据。
    SqlDataReader
    不是数据,它是一个实现细节,应该对其他层隐藏,以维护此体系结构背后的基本思想。我上面也提到过,好的。我同意你的方法。Thanks@ankitGupta:没问题,不客气。请把我的帖子标记为答案,如果你认为它对你有帮助的话。