应用程序的业务层是否应该能够访问Session对象?

时间:2009-05-29 18:24:53

标签: c# session business-logic

假设您有3层:UI,业务,数据。

如果Business Layer需要访问Sessions,这是否是设计不佳的标志?关于它的一些事情感觉不对。是否有专门针对Web应用程序定制的指南?

我使用c#2.0 .net

10 个答案:

答案 0 :(得分:5)

没有。如果你有一个“控制器”图层,你应该在那里访问它。从会话中获取所需内容并将其交给业务层。

答案 1 :(得分:5)

叹息。

广泛的共识将是不对的;业务层和控制器/网络层应该以不同的方式进行维护,因为它们是不同的问题。

事实上,你似乎把这标记为“纯粹与现实”的问题,这个问题令人难以置信地短视而且有些讨厌。它也无视提问的问题;如果你不考虑提出的意见,那么为什么要征求它们呢?

事实上,事先将事情分开一点点需要更多的前期努力,更多的时间,最终可能会花费更多。你也许无法从这样做中感受到任何直接的好处。然而,数十年来大量程序员共享的大量啜泣故事表明,在可能的情况下,你所谓的“纯度”可以减少5年后的痛苦;天哪;你真的不得不捏造并做一些重构,因为你的责任正在渗透所有的裂缝,所以它并不令人愉快。

为Web应用程序设想层的稍微好一点的方法可能是考虑表示,交互,业务规则和数据;从上到下。您的数据是数据库,数据访问等,业务规则对该数据强制执行任何其他约束,处理数据,计算等。然后交互然后在表示层(基本上是您的用户界面)和业务逻辑之间分支,执行驱动您的应用程序的用例。

到目前为止,用户界面并不重要;如果用户在命令行应用程序中输入客户数据,或者使用存储在会话中的数据导航某些多页Web表单,则无关紧要。让我们说你选择后者;将网络前端贴在上面。现在您关注的是编写相对简单的代码来处理检索所请求的数据并将其呈现给用户。关键是,您的Web应用程序;前端, 是您的整个用户界面;会议和所有。只有在您准备好说的时候,“嘿,让我们将客户数据粘贴到数据库中”您是否会调用那些精心制作的服务层,传递您的Web应用程序所获得的每一点信息藏匿;用户输入,进行更改的用户的名称;所有的废话。您的服务层处理它。或者,或者,母狗因为你忘记了必填字段。

因为你已经把事情彻底分开了,所以应用程序的内容可以像其他人所建议的那样被重新构建(或“借用”)以用于任何其他应用程序,并且服务层保持,无状态,干净,以及准备处理事情。它会进行验证,因此您的验证在任何地方都是一致的。但它不知道谁登录到Web前端,控制台应用程序或终端上运行的花哨的富客户端应用程序,并不关心,因为该细节仅对这些应用程序很重要。

需要添加新的验证规则吗?没问题;使服务层执行验证,并在链中更高的位置处理用户界面问题。需要改变计算方式吗?在业务层更改它。没有其他任何东西需要受到影响。

答案 2 :(得分:3)

闻起来很有趣。也许您需要一个表示层来管理会话和任何其他有状态信息?

答案 3 :(得分:3)

我认为业务逻辑不应该与表示选择相关联,如果Session存在于该层中,它将被束缚。

答案 4 :(得分:3)

我认为Session的不必要使用通常是代码味道,通常查询字符串,cookie和viewstate更轻,并且具有更好的“范围”

对于Sessions在业务层中的角色,它取决于您目前正在阅读的建筑专家。如果业务逻辑层是一个独立于UI的代码的位置,则Session不是引入业务层的东西。

例如,在控制台应用程序,ASP.NET Web应用程序,Windows服务和Windows窗体应用程序中 - 只有ASP.NET具有会话。

也就是说,能够支持多个用户界面是一个非常被高估的功能,并且它不会完全预见到估计你是否会将你的应用程序移植到不同的用户界面。如果您非常确信您的逻辑将从现在开始永久运行在ASP.NET应用程序中,那么它就可以了。

一个例外是单元测试。 nUnit测试运行器构成了不同的UI,很难模拟请求,响应,会话,应用程序等。

答案 5 :(得分:1)

我的感觉是,业务层是唯一可以访问会话数据的地方,因为它确实是您逻辑的一部分。如果将其烘焙到表示层,那么如果更改数据的存储位置(让我们说,您不再需要使用会话状态),那么进行更改会更加困难。

我要做的是对于会话状态的所有数据,我创建一个类来封装对该数据的检索。这将允许未来的变化。

编辑:UI只应用于执行以下操作: 1.呼叫业务层。 2.与用户交互(消息和事件)。 3.在屏幕上操纵视觉对象。

我听说有人认为会话数据访问是数据层的一部分,这是语义的,取决于你认为的数据层。

答案 6 :(得分:0)

如果保留列出的三个图层,“商务”图层可能最适合处理会话对象。

由于会话与将应用程序绑定在一起的实际框架而不是任何实际业务逻辑有关,因此您可能需要创建一个控制层,将Session对象中的数据转换为业务层的业务数据输入。 / p>

答案 7 :(得分:0)

我认为这取决于使用情况,但是,我们始终从业务层访问会话。这里也有一个“纯粹与现实”的论点。

例如,在我们的应用程序中,每个客户端都有一个数据库,但只有一个代码库。因此,我们在会话中为每个用户提供了客户端信息。当然,我们可以将该数据从Web层中的会话中提取出来,然后将其传递给业务层。当然,业务层甚至不关心它,但数据层需要连接到正确的数据库。那么业务层需要将其传递给数据层。似乎很多参数传递没有好的商业原因。在我们的例子中,我们的数据层检查会话对象的连接字符串并从那里运行。如果它不是一个Web应用程序(我们有Windows服务和.exe助手应用程序),我们编写了没有会话的问题,如下所示:

protected virtual string GetConnectionString()
{
string connectionString;
string connectionStringSource;

//In app.config?
if (ConfigurationManager.AppSettings[_ConnectionStringName] != null &&
   ConfigurationManager.AppSettings[_ConnectionStringName] != "")
{
   connectionString = ConfigurationManager.AppSettings[_ConnectionStringName];
   connectionStringSource = "Config settings";
}
//Nope? Check Session
else if (null != HttpContext.Current && null != HttpContext.Current.Session &&
   null != HttpContext.Current.Session[_ConnectionStringName])
{
  connectionString = (string)HttpContext.Current.Session[_ConnectionStringName];
  connectionStringSource = "Session";
}
//Nope? Check Thread
else if (null != System.Threading.Thread.GetData(
      System.Threading.Thread.GetNamedDataSlot(_ConnectionStringName)))
{
   connectionString = (string)System.Threading.Thread.GetData(
          System.Threading.Thread.GetNamedDataSlot(_ConnectionStringName));
   connectionStringSource = "ThreadLocal";
}
else
{
   throw new ApplicationException("Can't find a connection string");
}

if (debugLogging)
   log.DebugFormat("Connection String '{0}' found in {1}", connectionString, 
          connectionStringSource);

return connectionString;
}

答案 8 :(得分:0)

从业务层访问会话绝对是代码味道。

如果您需要按照规定“切换”业务层,您的表示层或控制器就需要担心会话变量是什么。

例如,假设您要为一个会话变量使用一组对象而为另一个变量使用另一组对象。您的控制器可以调用服务层并传入变量。然后,服务层将返回相应的业务对象。

您的业务层没有任何关于会话的业务,因为您的表示层没有业务知道您如何连接到数据库。

答案 9 :(得分:0)

会话对象与特定的UI实现相关联,因此让您的业务层在会话中死亡是一种气味。

另外,您可能应该能够对业务层进行单元测试 - 如果会话存在依赖关系,您将如何实现?