zoukankan      html  css  js  c++  java
  • LINQtoSQL那点事~线程共享的DbContext与私有的DbContext

    回到目录    

      在使用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, DataContext[]> divDataContext = new Dictionary<Thread, DataContext[]>();
     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 DataContextIntance(string dbName)
     57         {
     58             return Intance(dbName, Thread.CurrentThread, 1, 0);
     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 DataContextIntance(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 DataContextIntance(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 DataContextIntance(string dbName, Thread thread)
    101         {
    102             return Intance(dbName, thread, 1, 0);
    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, 2, 1))
    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     }

    回到目录

  • 相关阅读:
    UVA 11925 Generating Permutations 生成排列 (序列)
    UVA 1611 Crane 起重机 (子问题)
    UVA 11572 Unique snowflakes (滑窗)
    UVA 177 PaperFolding 折纸痕 (分形,递归)
    UVA 11491 Erasing and Winning 奖品的价值 (贪心)
    UVA1610 PartyGame 聚会游戏(细节题)
    UVA 1149 Bin Packing 装箱(贪心)
    topcpder SRM 664 div2 A,B,C BearCheats , BearPlays equalPiles , BearSorts (映射)
    UVA 1442 Cave 洞穴 (贪心+扫描)
    UVA 1609 Foul Play 不公平竞赛 (构(luan)造(gao)+递归)
  • 原文地址:https://www.cnblogs.com/lori/p/2653426.html
Copyright © 2011-2022 走看看