如何将数据读取器值从 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 传递到表示层的主要内容,如果未能解决你的问题,请参考以下文章
如何根据 Kotlin 中的键值从 firebase 读取数据
有没有办法将值从 Quartz Job 传递到 MVC 控制器?