管理业务层,数据层,datacontext实例asp.net网站的生命周期的最佳实践

时间:2012-08-22 13:59:16

标签: asp.net linq-to-sql datacontext lifecycle

我们的Asp.net Web应用程序正在使用LINQ-to-SQL(存储过程被拖放到dbml文件上以创建类)和 3层架构类似于下面的架构。我刚刚创建了粗略的方法来给读者提供正确的想法 他能回答得很好。请为我提供更长的代码

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 ...
        }
        ...             
    }
}

问题

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

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

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

非常感谢

2 个答案:

答案 0 :(得分:1)

  

(参考文献#1)在DataAccess中使用全局datacontext是一种好方法吗?是/否为什么?

是。

但是,在dataaccess类中手动创建它意味着您无法控制datacontext的生存期。而是将其设置为构造函数参数,以便将其注入数据访问

  

(参考文献#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"];
     } 
  }
}

答案 1 :(得分:0)

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

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

肯定你应该使用DataContextes更短或同时使用Request,不要尝试使用LongSession(当你试图为多个Http请求保留DataContext时,它只是痛苦的屁股,没有别的,如果你想阅读这篇文章,试着阅读关于Hibernate中长跑会话的几篇文章,我试过用nHibernate - 不要在家里做这个;))。