1

我们的 Asp.net Web 应用程序使用 LINQ-to-SQL(Stored Procs 被拖放到 dbml 文件上以创建类),三层架构类似于下面的架构。我刚刚创建了粗略的方法来给读者正确的想法,以便他能够很好地回答。

namespace MyDataLayer
{
    public class MyDataAccess
    {
        // global instance of datacontext
        MyDataModelDataContext myDB = new MyDataModelDataContext();     (#1)

        public void GetUserIDByUsername(string sUserName, ref int iUserID)
        {
            int? iUserIDout = 0;
            // this will make call to SP in SQL DB
            myDB.USP_RP_GETUSERIDBYUSERNAME(sUserName, "", ref iUserIDout);
            iUserID = (int)iUserIDout;
        }

        public List<USP_APP_USERDETAILSResult> GetUserDetails(string sUserIDs)
        {
            // this will make call to SP in SQL DB
            return myDB.USP_APP_USERDETAILS(sUserIDs).ToList();
        }
        ...
        ... // several CRUD methods
    }
}

namespace MyBusinessLayer
{
    public class SiteUser
    {
        // global DataAccess instance
        MyDataLayer.MyDataAccess myDA = new MyDataAccess();             (#2)
        public void GetUserIDByUsername(string sUserName, ref int iUserID)
        {
            myDA.GetUserIDByUsername(sUserName, ref iUserID);
        }
        public List<USP_APP_USERDETAILSResult> GetUserDetails(string sUserIDs)
        {
            // this will make call to SP in SQL DB
            return myDA.GetUserDetails(sUserIDs);
        }
        ...
        ... // several CRUD methods
    }
}

namespace MyWebApplication
{
    public class BaseWebPage : System.Web.UI.Page
    {
        // static business layer instance
        public static MyBusinessLayer.SiteUser UserBLInstance = new SiteUser();         (#3)                    
        ...             
    }
}
// Index.aspx.cs code fragment
namespace MyWebApplication
{
    public class Index : BaseWebPage
    {       
        public void PopulateUserDropDown()
        {
            // using static business layer instance declared in BaseWebPage
            List<USP_APP_USERDETAILSResult> listUsers = UserBLInstance.GetUserDetails("1,2,3");

            // do databinding and so on ...
        }
        ...             
    }
}

问题

  • (Ref.#1)在 DataAccess 中有全局数据上下文是好方法吗?是/否 为什么?
  • 如果您的建议是每个请求都有数据上下文,那么最佳实践是什么
  • (Ref.#2)在 BusinessLayer 中拥有全局 DataAccess 实例是好方法吗?是/否 为什么?
  • 如果您的建议是每个请求都有 DataAccess 实例,那么最佳做法是什么
  • (参考#3)在 BaseWebPage 中声明的静态业务层实例是好方法吗?是/否 为什么?
  • 一般管理 BL 实例和 DL 实例的生命周期的最佳方法

我们在生产服务器上面临周期性的 InvalidCastException,这是一个非常简单的方法,如果我从 IIS 重新启动我的应用程序,它可以正常工作。当出现此问题时,我们可以从 SQL Management Studio 访问相同的数据库并执行相同的 SP

我们对这个问题的主要怀疑是 DataContext 管理不善,我在网上阅读了很多关于管理 DataContext 生命周期的文章,但我现在对各种方法感到困惑。这就是为什么我详细阐述了我的问题,以便许多处于相同情况的人可以清楚地了解问题/答案。

4

2 回答 2

1

(Ref.#1)在 DataAccess 中有全局数据上下文是好方法吗?是/否 为什么?

是的。

但是,在数据访问类中手动创建它意味着您无法控制数据上下文的生命周期。相反,将其设置为构造函数参数,以便将其注入数据访问

(Ref.#2)在 BusinessLayer 中拥有全局 DataAccess 实例是好方法吗?是/否 为什么?

是的。但请参阅 1. -通过构造函数使其可注入。

(参考#3)在 BaseWebPage 中声明的静态业务层实例是好方法吗?是/否 为什么?

不。避免复杂对象的静态,因为这些对象通常具有非平凡的状态。如果您在并发环境中共享此类对象,则会发生许多令人讨厌的问题。

总结一下。

public class DataAccess {
   public DataAccess( DataContext context ) { ... }    
}

public class BusinessLayer {
   public BusinessLayer( DataAccess access ) { ... }    
}

public class MyPage : Page {
 ...

 var ctx = TheDataContext.Current;
 var bl = new BusinessLayer( new DataAccess( ctx ) );  
}

在请求范围内共享数据上下文:

public partial class TheDataContext {

  // Allow the datacontext to be shared in a request-scope
  public static TheDataContext Current {
     get {
         if ( HttpContext.Current.Items["context"] == null )
            HttpContext.Current.Items.Add( "context", new TheDataContext() );

         return (TheDataContext)HttpContext.Current.Items["context"];
     } 
  }
}
于 2012-08-22T14:37:42.350 回答
0

在您的示例中 - 您的 MyDataLayer 通常具有名称存储库。在 Repositories 中拥有 DataContext 实例并且不要尝试在外部使用它们绝对是一件好事。因此,只有在存储库中,您才会依赖于 Linq-To-Sql,这意味着您可以为这些存储库创建 Stub 对象,并且非常容易测试应用程序的其他部分。

绝对应该 Dispose 你的 Data Context 实例,DataContext 包含太多的对象,无法让它们保持活动状态并让 GC 杀死它们。正如您所看到的,您在使用 DataContextes 时不会创建任何事务对象,所以我认为 LinqToSql 的理念是您应该拥有每个事务的所有内容(当然您也可以尝试手动处理事务,但您真的想这样做吗?)。在 Repository 的方法中处理数据上下文是一个好方法,因为这将不允许您使用所有 ORM 框架的酷特性:延迟加载。如果您尝试使用延迟加载 - 您会喜欢它,但通常它只是可能的性能下降原因之一。

绝对你应该使用 DataContextes 更短或相同的请求时间,不要尝试使用 LongSession (这是当你试图为多个 Http 请求保留 DataContext 时,如果你想要的话,这只是屁股的痛苦,仅此而已要了解这一点,只需尝试阅读有关 Hibernate 中的长时间运行会话的几篇文章,我尝试使用 nHibernate - 不要在家里这样做;))。

于 2012-08-22T14:26:28.540 回答