如何将数据读取器值从 DAL 传递到表示层

Posted

技术标签:

【中文标题】如何将数据读取器值从 DAL 传递到表示层【英文标题】:How to pass datareader value from DAL to presentation layer 【发布时间】:2013-01-08 06:12:11 【问题描述】:

我正在开发一个使用 3 层架构的项目。 我想知道如何将 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对象。

【问题讨论】:

【参考方案1】:

在 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())


【讨论】:

【参考方案2】:

嗯,分层架构的基本思想是将不同的组件解耦,原因有几个。 一些原因是可测试性、可维护性、可扩展性,但还有更多。

要在这些层之间传递数据——这在一定程度上取决于数据的类型——但通常你会使用一些简单的类作为数据传输对象 (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;
    
 

会是更好的方法。

【讨论】:

谢谢老兄,但是你现在能给我一个合适的解决方案如何使用sqldatareader吗?我向你展示了我的架构,我知道它有问题。但现在我该如何纠正这些错误。请在我向您展示我的代码时向我展示解决方案。在 DAL 和 BLL 文件中做什么 @ankitGupta:我不确定,为什么您在我们的解释后没有看到解决方案,但请看我的编辑。 @ankitGupta:好吧,如果它对你有用,那就没有错。但是考虑到分层架构,这是完全错误的,因为你没有分离任何东西。正如我在上面的帖子中所描述的,唯一应该由 DAL 发布的是通过 DTO 发布的数据。 SqlDataReader 不是数据,它是一个实现细节,应该对其他层隐藏,以保持该架构背后的基本思想。我在上面也提到了这一点。 好的。我会用你的方法。谢谢 @ankitGupta:没问题,不客气。请将我的帖子标记为答案,如果您认为它对您有帮助。【参考方案3】:

我认为你的架构有问题;

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

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

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

建议你参考n layer reference application of microsoft spain

【讨论】:

谢谢先生,你能用一个很好的例子来解释我吗?在这个场景中做什么。 如果你参考我提供的链接,有详细的解释。在这里解释太长了(概念很多,需要根据自己的需要决定使用或不使用)。 谢谢老兄,我知道我的架构存在问题。但现在我想纠正这些错误。请在我向您展示我的代码时向我展示解决方案。在 DAL 和 BLL 文件中做什么。

以上是关于如何将数据读取器值从 DAL 传递到表示层的主要内容,如果未能解决你的问题,请参考以下文章

使用 LINQ 作为 DAL 时如何传输数据?

如何根据 Kotlin 中的键值从 firebase 读取数据

将值从数据库传递到 vue 组件并将其分配给变量

有没有办法将值从 Quartz Job 传递到 MVC 控制器?

如何将用于审计目的的 web n 层应用程序中的用户身份从用户界面层传递到数据访问层?

C# |如何制作用于将数据从 DAL 传递到 BLL 的类实例(对象)