博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LINQ-to-SQL那点事~线程共享的DbContext与私有的DbContext
阅读量:6240 次
发布时间:2019-06-22

本文共 10948 字,大约阅读时间需要 36 分钟。

    

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

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

1     ///  2         /// 使用默认的连接串创建实现(每拖一次数据库,就会产生一个连接串) 3         ///  4         public DataClasses1DataContext() :  5                 base(global::test.Properties.Settings.Default.EEE114ConnectionString, mappingSource) 6         { 7             OnCreated(); 8         } 9         /// 10         /// 使用指定的连接串,可能配置在config文件里11         /// 12         /// 13         public DataClasses1DataContext(string connection) : 14                 base(connection, mappingSource)15         {16             OnCreated();17         }18         /// 19         /// 使用使用了IDbConnection接口的对象创建实例20         /// 21         /// 22         public DataClasses1DataContext(System.Data.IDbConnection connection) : 23                 base(connection, mappingSource)24         {25             OnCreated();26         }27         /// 28         /// 使用连接串和数据库的映射文件来建立实例,mappingSource可能是一个XML文件29         /// 30         /// 31         /// 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     ///   2     /// 数据库建立工厂  3     /// Created By : 张占岭  4     /// Created Date:2011-10-14  5     /// Modify By:  6     /// Modify Date:  7     /// Modify Reason:  8     ///   9     internal sealed class DbFactory 10     { 11         #region Fields 12         static System.Timers.Timer sysTimer = new System.Timers.Timer(10000); 13         volatile static Dictionary
divDataContext = new Dictionary
(); 14 #endregion 15 16 #region Constructors 17 ///
18 /// 类构造方法 19 /// 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 ///
32 /// 订阅Elapsed事件的方法 33 /// 34 ///
35 ///
36 static void sysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 37 { 38 List
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 ///
52 /// 通过工厂的制造模式获取相应的LINQ数据库连接对象 53 /// 54 ///
数据库名称(需要与真实数据库名称保持一致) 55 ///
LINQ数据库连接对象
56 public static DataContextIntance(string dbName) 57 { 58 return Intance(dbName, Thread.CurrentThread, 1, 0); 59 } 60 61 ///
62 /// 通过工厂的制造模式获取相应的LINQ数据库连接对象 63 /// 64 ///
65 ///
66 ///
67 ///
68 public static DataContextIntance(string dbName, int dbCount, int dbIndex) 69 { 70 return Intance(dbName, Thread.CurrentThread, dbCount, dbIndex); 71 } 72 73 ///
74 /// 通过工厂的制造模式获取相应的LINQ数据库连接对象 75 /// 76 ///
数据库名称(需要与真实数据库名称保持一致) 77 ///
当前线程引用的对象 78 ///
linq to sql数据库数量 79 ///
当前索引 80 ///
LINQ对象上下文
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 ///
95 /// 通过工厂的制造模式获取相应的LINQ数据库连接对象 96 /// 97 ///
98 ///
99 ///
100 public static DataContextIntance(string dbName, Thread thread)101 {102 return Intance(dbName, thread, 1, 0);103 }104 #endregion105 106 }

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

1 ///  2     /// XXB数据库基类 3     ///  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             else12                 _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  /// 2     /// XXB数据基类3     /// 4     public abstract class XXBBase : DataBase5     {6         public XXBBase()7             : base(new LINQ.DataClasses1DataContext(System.Configuration.ConfigurationManager.ConnectionStrings["XXB"].ToString()))8         { }9     }

统一数据基类:

1   ///   2     /// 标准数据操作基类  3     ///   4     public abstract class DataBase : IRepository  5     {  6         ///   7         /// 数据访问对象(只对子类可见)  8         ///   9         protected DataContext DB; 10  11         #region Constructors 12         public DataBase(DataContext db) 13             : this(() => { return db; }) 14         { } 15         public DataBase(Func
func) 16 { 17 this.DB = func(); 18 } 19 #endregion 20 21 #region DBContext SubmitChanges 22 ///
23 /// XXB默认提交【重写时候可能需要写入自定义的类似约束的逻辑】 24 /// 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 entity) where TEntity : class 54 { 55 this.SubmitChanges(); 56 57 } 58 59 public virtual void Update
(IEnumerable
list) where TEntity : class 60 { 61 list.ToList().ForEach(entity => 62 { 63 this.Update
(entity); 64 }); 65 } 66 67 public virtual void Insert
(TEntity entity) where TEntity : class 68 { 69 DB.GetTable
().InsertOnSubmit(entity); 70 this.SubmitChanges(); 71 } 72 73 public virtual void Insert
(IEnumerable
list) where TEntity : class 74 { 75 DB.GetTable
().InsertAllOnSubmit
(list); 76 this.SubmitChanges(); 77 } 78 79 public virtual TEntity InsertGetIDENTITY
(TEntity entity) where TEntity : class 80 { 81 this.Insert
(entity); 82 return GetModel
(i => i == entity).FirstOrDefault(); 83 } 84 85 public virtual void Delete
(TEntity entity) where TEntity : class 86 { 87 DB.GetTable
().DeleteOnSubmit(entity); 88 this.SubmitChanges(); 89 } 90 91 public virtual void Delete
(IEnumerable
list) where TEntity : class 92 { 93 DB.GetTable
().DeleteAllOnSubmit
(list); 94 this.SubmitChanges(); 95 } 96 97 public virtual IQueryable
GetModel
() where TEntity : class 98 { 99 return this.DB.GetTable
();100 }101 102 public virtual IQueryable
GetModel
(System.Linq.Expressions.Expression
> predicate) where TEntity : class103 {104 return GetModel
().Where(predicate);105 }106 107 public virtual TEntity Find
(params object[] keyValues) where TEntity : class108 {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
().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 #endregion118 }

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

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

回到目录

转载于:https://www.cnblogs.com/lori/archive/2012/08/23/2653426.html

你可能感兴趣的文章