线程共享的DbContext与私有的DbContext

开发 架构
在使用Linq to Sql做为底层ORM时,它为我们提供的数据上下文为DataContext对象,实现上我们通过拖动生成的DBML文件,它们都是继承自 System.Data.Linq.DataContext类型的,所以DataContext就是LINQ数据对象的基类,有时,我们可以通过这种类的多态性来动态创建DB的实例。

在使用Linq to Sql做为底层ORM时,它为我们提供的数据上下文为DataContext对象,实现上我们通过拖动生成的DBML文件,它们都是继承自 System.Data.Linq.DataContext类型的,所以DataContext就是LINQ数据对象的基类,有时,我们可以通过这种类的多态性来动态创建DB的实例。

在每个DataContext类中,它有几个实例的构造方法,用来让你创建DataContext的实例,如下:

  1. /// <summary>  
  2.          /// 使用默认的连接串创建实现(每拖一次数据库,就会产生一个连接串)  
  3.          /// </summary>  
  4.          public DataClasses1DataContext() :   
  5.                  base(global::test.Properties.Settings.Default.EEE114ConnectionString, mappingSource)  
  6.          {  
  7.              OnCreated();  
  8.          }  
  9.          /// <summary>  
  10.          /// 使用指定的连接串,可能配置在config文件里  
  11.          /// </summary>  
  12.          /// <param name="connection"></param>  
  13.          public DataClasses1DataContext(string connection) :   
  14.                  base(connection, mappingSource)  
  15.          {  
  16.              OnCreated();  
  17.          }  
  18.          /// <summary>  
  19.          /// 使用使用了IDbConnection接口的对象创建实例  
  20.          /// </summary>  
  21.          /// <param name="connection"></param>  
  22.          public DataClasses1DataContext(System.Data.IDbConnection connection) :   
  23.                  base(connection, mappingSource)  
  24.          {  
  25.              OnCreated();  
  26.          }  
  27.          /// <summary>  
  28.          /// 使用连接串和数据库的映射文件来建立实例,mappingSource可能是一个XML文件  
  29.          /// </summary>  
  30.          /// <param name="connection"></param>  
  31.          /// <param name="mappingSource"></param>  
  32.          public DataClasses1DataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :   
  33.                  base(connection, mappingSource)  
  34.          {  
  35.              OnCreated();  
  36.          } 

而我们在实现项目开发中,可能用第二种比较多,即

  1. DataClasses1DataContext db=new LINQ.DataClasses1DataContext(System.Configuration.ConfigurationManager.ConnectionStrings["XXB"].ToString()) 

这样,在开发环境与生成环境只要配置一个CONFIG文件即可。灵活。

而今天的主题是线程共享的DbContext与私有的DbContext,所以开始书归正转了,对于ado.net架构中,我们往往使用一个static全局对象来完成数据访问工作,而在linq to sql中,如果你建立一个static对象,它会出现很多问题,这在实现开发过程中才可以体会到,所以,今天要说的不是static对象。

一 线程共享的DbContext,说清楚一点就是在一个线程内,你的DataContext对象是共享的,是一个对象,不是new出很多个datacontext对象来,这事实上是一种单例模式的体现,这没有问题,它解决了static对象所产生的问题,而又满足了多表关联查询时出现(不能实现不同数据上下文件的引用,linq to sql和Ef都是这样的)的问题。

代码:

datacontext生成工厂:

  1. /// <summary>  
  2.      /// 数据库建立工厂  
  3.      /// Created By : 张占岭  
  4.      /// Created Date:2011-10-14  
  5.      /// Modify By:  
  6.      /// Modify Date:  
  7.      /// Modify Reason:  
  8.      /// </summary>  
  9.      internal sealed class DbFactory  
  10.      {  
  11.          #region Fields  
  12.          static System.Timers.Timer sysTimer = new System.Timers.Timer(10000);  
  13.          volatile static Dictionary<Thread, DbContext[]> divDataContext = new Dictionary<Thread, DbContext[]>();  
  14.          #endregion  
  15.    
  16.          #region Constructors  
  17.          /// <summary>  
  18.          /// 类构造方法  
  19.          /// </summary>  
  20.          static DbFactory()  
  21.          {  
  22.              sysTimer.AutoReset = true;  
  23.              sysTimer.Enabled = true;  
  24.              sysTimer.Elapsed += new System.Timers.ElapsedEventHandler(sysTimer_Elapsed);  
  25.              sysTimer.Start();  
  26.          }  
  27.          #endregion  
  28.    
  29.          #region  Static Methods  
  30.    
  31.          /// <summary>  
  32.          /// 订阅Elapsed事件的方法  
  33.          /// </summary>  
  34.          /// <param name="sender"></param>  
  35.          /// <param name="e"></param>  
  36.          static void sysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)  
  37.          {  
  38.              List<Thread> list = divDataContext.Keys.Where(item => item.ThreadState == ThreadState.Stopped).ToList();  
  39.              for (int index = 0; index < list.Count; index++)  
  40.              {  
  41.                  for (int refer = 0; refer < divDataContext[list[index]].Length; refer++)  
  42.                      if (divDataContext[list[index]][refer] != null)  
  43.                      {  
  44.                          divDataContext[list[index]][refer].Dispose();  
  45.                          divDataContext[list[index]][refer] = null;  
  46.                      }  
  47.                  divDataContext.Remove(list[index]);  
  48.                  list[index] = null;  
  49.              }  
  50.          }  
  51.          /// <summary>  
  52.          /// 通过工厂的制造模式获取相应的LINQ数据库连接对象  
  53.          /// </summary>  
  54.          /// <param name="dbName">数据库名称(需要与真实数据库名称保持一致)</param>  
  55.          /// <returns>LINQ数据库连接对象</returns>  
  56.          public static DbContext Intance(string dbName)  
  57.          {  
  58.              return Intance(dbName, Thread.CurrentThread, 10);  
  59.          }  
  60.    
  61.          /// <summary>  
  62.          /// 通过工厂的制造模式获取相应的LINQ数据库连接对象  
  63.          /// </summary>  
  64.          /// <param name="dbName"></param>  
  65.          /// <param name="dbCount"></param>  
  66.          /// <param name="dbIndex"></param>  
  67.          /// <returns></returns>  
  68.          public static DbContext Intance(string dbName, int dbCount, int dbIndex)  
  69.          {  
  70.              return Intance(dbName, Thread.CurrentThread, dbCount, dbIndex);  
  71.          }  
  72.    
  73.          /// <summary>  
  74.          /// 通过工厂的制造模式获取相应的LINQ数据库连接对象  
  75.          /// </summary>  
  76.          /// <param name="dbName">数据库名称(需要与真实数据库名称保持一致)</param>  
  77.          /// <param name="thread">当前线程引用的对象</param>  
  78.          /// <param name="dbCount">linq to sql数据库数量</param>  
  79.          /// <param name="dbIndex">当前索引</param>  
  80.          /// <returns>LINQ对象上下文</returns>  
  81.          public static DbContext Intance(string dbName, Thread thread, int dbCount, int dbIndex)  
  82.          {  
  83.              if (!divDataContext.Keys.Contains(thread))  
  84.              {  
  85.                  divDataContext.Add(thread, new DbContext[dbCount]);  
  86.              }  
  87.              if (divDataContext[thread][dbIndex] == null)  
  88.              {  
  89.                  divDataContext[thread][dbIndex] = new DbContext(dbName);  
  90.              }  
  91.              return divDataContext[thread][dbIndex];  
  92.          }  
  93.    
  94.          /// <summary>  
  95.          /// 通过工厂的制造模式获取相应的LINQ数据库连接对象  
  96.          /// </summary>  
  97.          /// <param name="dbName"></param>  
  98.          /// <param name="thread"></param>  
  99.          /// <returns></returns>  
  100.          public static DbContext Intance(string dbName, Thread thread)  
  101.          {  
  102.              return Intance(dbName, thread, 10);  
  103.          }  
  104.          #endregion  
  105.    
  106.      } 

具体领域数据对象创建时代码如下:

  1. /// <summary>  
  2.      /// XXB数据库基类  
  3.      /// </summary>  
  4.      public class XXB_DataBase : DataBase  
  5.      {  
  6.          private readonly static string _conn;  
  7.          static XXB_DataBase()  
  8.          {  
  9.              if (ConfigurationManager.ConnectionStrings["XXB"] == null)  
  10.                  throw new Exception("请设置XXB配置字符");  
  11.              else 
  12.                  _conn = ConfigurationManager.ConnectionStrings["XXB"].ToString();  
  13.          }  
  14.          public XXB_DataBase()  
  15.              : base(DbFactory.Intance(_conn, 21))  
  16.          { }  
  17.    
  18.      } 

二 私有的DbContext,它要求你为每个表都建立一个repository对象,用户对表进行CURD操作,而它们都继承一个database,在 database里有唯一创建datacontext的入口,这样在做多表关联时,使用的是同一个datacontext对象,所以不会出现“不能实现不同数据上下文件的引用”这种问题,但这样方式感觉很不爽,因为你必须把所有多表关联的业务逻辑,写在DAL层,这是很郁闷的,因为一般我们会把它放在BLL层(更有利于业务的组合与重用)。

代码:

具体领域数据基类:

  1. /// <summary>  
  2.      /// XXB数据基类  
  3.      /// </summary>  
  4.      public abstract class XXBBase : DataBase  
  5.      {  
  6.          public XXBBase()  
  7.              : base(new LINQ.DataClasses1DataContext(System.Configuration.ConfigurationManager.ConnectionStrings["XXB"].ToString()))  
  8.          { }  
  9.      } 

统一数据基类:

  1. /// <summary>  
  2.      /// 标准数据操作基类  
  3.      /// </summary>  
  4.      public abstract class DataBase : IRepository  
  5.      {  
  6.          /// <summary>  
  7.          /// 数据访问对象(只对子类可见)  
  8.          /// </summary>  
  9.          protected DataContext DB;  
  10.    
  11.          #region Constructors  
  12.          public DataBase(DataContext db)  
  13.              : this(() => { return db; })  
  14.          { }  
  15.          public DataBase(Func<DataContext> func)  
  16.          {  
  17.              this.DB = func();  
  18.          }  
  19.          #endregion  
  20.    
  21.          #region DBContext SubmitChanges  
  22.          /// <summary>  
  23.          /// XXB默认提交【重写时候可能需要写入自定义的类似约束的逻辑】  
  24.          /// </summary>  
  25.          protected virtual void SubmitChanges()  
  26.          {  
  27.              ChangeSet cSet = DB.GetChangeSet();  
  28.              if (cSet.Inserts.Count > 0 
  29.                  || cSet.Updates.Count > 0 
  30.                  || cSet.Deletes.Count > 0)  
  31.              {  
  32.                  try 
  33.                  {  
  34.                      DB.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);  
  35.                  }  
  36.                  catch (System.Data.Linq.ChangeConflictException)  
  37.                  {  
  38.                      foreach (System.Data.Linq.ObjectChangeConflict occ in DB.ChangeConflicts)  
  39.                      {  
  40.                          occ.Resolve(System.Data.Linq.RefreshMode.OverwriteCurrentValues);  
  41.                          occ.Resolve(System.Data.Linq.RefreshMode.KeepCurrentValues);  
  42.                          occ.Resolve(System.Data.Linq.RefreshMode.KeepChanges);  
  43.                      }  
  44.                      DB.SubmitChanges();  
  45.                  }  
  46.              }  
  47.          }  
  48.    
  49.          #endregion  
  50.    
  51.          #region IRepository 成员  
  52.    
  53.          public virtual void Update<TEntity>(TEntity entity) where TEntity : class 
  54.          {  
  55.              this.SubmitChanges();  
  56.    
  57.          }  
  58.    
  59.          public virtual void Update<TEntity>(IEnumerable<TEntity> list) where TEntity : class 
  60.          {  
  61.              list.ToList().ForEach(entity =>  
  62.              {  
  63.                  this.Update<TEntity>(entity);  
  64.              });  
  65.          }  
  66.    
  67.          public virtual void Insert<TEntity>(TEntity entity) where TEntity : class 
  68.          {  
  69.              DB.GetTable<TEntity>().InsertOnSubmit(entity);  
  70.              this.SubmitChanges();  
  71.          }  
  72.    
  73.          public virtual void Insert<TEntity>(IEnumerable<TEntity> list) where TEntity : class 
  74.          {  
  75.              DB.GetTable<TEntity>().InsertAllOnSubmit<TEntity>(list);  
  76.              this.SubmitChanges();  
  77.          }  
  78.    
  79.          public virtual TEntity InsertGetIDENTITY<TEntity>(TEntity entity) where TEntity : class 
  80.          {  
  81.              this.Insert<TEntity>(entity);  
  82.              return GetModel<TEntity>(i => i == entity).FirstOrDefault();  
  83.          }  
  84.    
  85.          public virtual void Delete<TEntity>(TEntity entity) where TEntity : class 
  86.          {  
  87.              DB.GetTable<TEntity>().DeleteOnSubmit(entity);  
  88.              this.SubmitChanges();  
  89.          }  
  90.    
  91.          public virtual void Delete<TEntity>(IEnumerable<TEntity> list) where TEntity : class 
  92.          {  
  93.              DB.GetTable<TEntity>().DeleteAllOnSubmit<TEntity>(list);  
  94.              this.SubmitChanges();  
  95.          }  
  96.    
  97.          public virtual IQueryable<TEntity> GetModel<TEntity>() where TEntity : class 
  98.          {  
  99.              return this.DB.GetTable<TEntity>();  
  100.          }  
  101.    
  102.          public virtual IQueryable<TEntity> GetModel<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate) where TEntity : class 
  103.          {  
  104.              return GetModel<TEntity>().Where(predicate);  
  105.          }  
  106.    
  107.          public virtual TEntity Find<TEntity>(params object[] keyValues) where TEntity : class 
  108.          {  
  109.              var mapping = DB.Mapping.GetTable(typeof(TEntity));  
  110.              var keys = mapping.RowType.IdentityMembers.Select((m, i) => m.Name + " = @" + i).ToArray();  
  111.              TEntity entityTEntity = DB.GetTable<TEntity>().Where(String.Join(" && ", keys), keyValues).FirstOrDefault();  
  112.              if (entityTEntity != null)  
  113.                  DB.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, entityTEntity);  
  114.              return entityTEntity;  
  115.          }  
  116.    
  117.          #endregion  
  118.      } 

而用户模块User_InfoRepository在做多表关联时,是这样完成的:

  1. public class User_InfoRepository : XXBBase  
  2.      {  
  3.          /// <summary>  
  4.          /// 需要把Join的表关系写在这里  
  5.          /// </summary>  
  6.          /// <returns></returns>  
  7.          public IQueryable<User_Info> GetDetailModel()  
  8.          {  
  9.              var linq = from data1 in base.GetModel<User_Info>()  
  10.                         join data2 in base.GetModel<User_Profile>() on data1.UserID equals data2.UserID  
  11.                         select data1;  
  12.              return linq;  
  13.          }  
  14.      } 

原文链接:http://www.cnblogs.com/lori/archive/2012/08/23/2653426.html

责任编辑:林师授 来源: 博客园
相关推荐

2021-02-04 18:04:53

DbContext开源对象

2013-09-08 21:41:10

RepositoryUnitOfWorkDbContext

2024-01-02 10:31:14

JVM内存整体

2020-03-09 15:42:11

网状网络开源FreeMesh

2012-03-27 14:25:23

私有云PaaS云计算

2011-09-29 09:48:39

私有云PaaS云计算

2011-09-15 09:31:32

云计算PaaS私有云

2013-12-16 17:17:01

OpenMp数据处理

2020-04-27 14:43:35

私有部署绘图服务

2021-07-01 20:24:01

开源开源工具虚拟专用网络

2022-03-17 08:30:28

Python私有属性私有方法

2011-05-23 16:12:39

私有云

2013-01-21 10:51:33

私有云EMCSyncplicity

2016-07-06 15:56:05

云计算

2011-10-21 14:24:03

私有云云计算

2024-04-08 10:09:37

TTLJava框架

2011-06-30 17:21:56

Qt 线程 共享

2013-07-17 09:40:13

虚拟化云计算

2012-10-09 09:37:08

虚拟化私有云计算云计算

2019-12-12 14:08:32

威胁情报威胁狩猎情报共享
点赞
收藏

51CTO技术栈公众号