public static FrmQuery Create(DAL db) { if (db == null) throw new ArgumentNullException("db"); FrmQuery frm = new FrmQuery(); frm.Dal = db; return frm; }
/// <summary>创建一个数据访问层对象。</summary> /// <param name="connName">配置名</param> /// <returns>对应于指定链接的全局唯一的数据访问层对象</returns> public static DAL Create(String connName) { if (String.IsNullOrEmpty(connName)) throw new ArgumentNullException("connName"); // 如果需要修改一个DAL的连接字符串,不应该修改这里,而是修改DAL实例的ConnStr属性 DAL dal = null; if (_dals.TryGetValue(connName, out dal)) return dal; lock (_dals) { if (_dals.TryGetValue(connName, out dal)) return dal; dal = new DAL(connName); // 不用connName,因为可能在创建过程中自动识别了ConnName _dals.Add(dal.ConnName, dal); } return dal; }
/// <summary>创建一个数据访问层对象。</summary> /// <param name="connName">配置名,或链接字符串</param> /// <returns>对应于指定链接的全局唯一的数据访问层对象</returns> public static DAL Create(String connName) { if (String.IsNullOrEmpty(connName)) throw new ArgumentNullException("connName"); DAL dal = null; if (_dals.TryGetValue(connName, out dal)) return dal; lock (_dals) { if (_dals.TryGetValue(connName, out dal)) return dal; ////检查数据库最大连接数授权。 //if (License.DbConnectCount != _dals.Count + 1) // License.DbConnectCount = _dals.Count + 1; dal = new DAL(connName); // 不用connName,因为可能在创建过程中自动识别了ConnName _dals.Add(dal.ConnName, dal); } return dal; }
/// <summary> /// 初始化数据库结构 /// </summary> private void InitDataSchema() { try { XTrace.WriteLine(String.Format("开始对数据库[{0}]的架构加载...", m_conn.Database.DatabaseName)); DAL.AddConnStr(m_conn.Database.ConnName, m_conn.ConnString, null, m_conn.Database.Provider); DAL dal = DAL.Create(m_conn.Database.ConnName); dal.Session.QuickTest(); m_dal = dal; m_tableCount = dal.Tables.FindAll(x => !x.IsView).Count; m_viewCount = dal.Tables.FindAll(x => x.IsView).Count; m_initStatus = DataSchemaInitStatus.Initialized; XTrace.WriteLine(String.Format("完成对数据库[{0}]的架构加载...", m_conn.Database.DatabaseName)); } catch (Exception ex) { m_initStatus = DataSchemaInitStatus.Error; m_initError = ex.Message; } finally { OnStatusChange(new StatusChangeEventArgs(m_initStatus)); } }
/// <summary>����һ�����ݷ��ʲ����</summary> /// <param name="connName">���������������ַ���</param> /// <returns>��Ӧ��ָ�����ӵ�ȫ��Ψһ�����ݷ��ʲ����</returns> public static DAL Create(String connName) { if (String.IsNullOrEmpty(connName)) throw new ArgumentNullException("connName"); DAL dal = null; if (_dals.TryGetValue(connName, out dal)) return dal; lock (_dals) { if (_dals.TryGetValue(connName, out dal)) return dal; ////������ݿ������������Ȩ�� //if (License.DbConnectCount != _dals.Count + 1) // License.DbConnectCount = _dals.Count + 1; dal = new DAL(connName); // ����connName����Ϊ�����ڴ����������Զ�ʶ����ConnName _dals.Add(dal.ConnName, dal); } return dal; }
DataTable GetSchemaInternal(String key, String collectionName, String[] restrictionValues) { QueryTimes++; //// 如果启用了事务保护,这里要新开一个连接,否则MSSQL里面报错,SQLite不报错,其它数据库未测试 //var isTrans = Transaction != null; //DbConnection conn = null; //if (isTrans) //{ // conn = Factory.CreateConnection(); // CheckConnStr(); // conn.ConnectionString = ConnectionString; // conn.Open(); //} //else //{ // if (!Opened) Open(); // conn = Conn; //} //// 连接未打开 //if (conn.State == ConnectionState.Closed) return null; using (var pi = Database.Pool.AcquireItem()) { var conn = pi.Value; //try //{ DataTable dt = null; var sw = Stopwatch.StartNew(); if (restrictionValues == null || restrictionValues.Length < 1) { if (String.IsNullOrEmpty(collectionName)) { WriteSQL("[" + Database.ConnName + "]GetSchema"); dt = conn.GetSchema(); } else { WriteSQL("[" + Database.ConnName + "]GetSchema(\"" + collectionName + "\")"); dt = conn.GetSchema(collectionName); } } else { var sb = new StringBuilder(); foreach (var item in restrictionValues) { sb.Append(", "); if (item == null) { sb.Append("null"); } else { sb.AppendFormat("\"{0}\"", item); } } WriteSQL("[" + Database.ConnName + "]GetSchema(\"" + collectionName + "\"" + sb + ")"); dt = conn.GetSchema(collectionName, restrictionValues); } sw.Stop(); // 耗时超过多少秒输出错误日志 if (sw.ElapsedMilliseconds > 1000) { DAL.WriteLog("GetSchema耗时 {0:n0}ms", sw.ElapsedMilliseconds); } return(dt); //} //catch (DbException ex) //{ // throw new XDbSessionException(this, "取得所有表构架出错!", ex); //} //finally //{ // if (isTrans) // conn.Close(); // else // AutoClose(); //} } }
/// <summary>代码生成测试</summary> /// <param name="dal"></param> public static void CodeTest(DAL dal) { //XTable table = dal.Tables[0]; //foreach (XTable item in dal.Tables) //{ // if (item.Name == "Area") // { // table = item; // break; // } //} EntityAssembly asm = new EntityAssembly(); asm.Dal = dal; asm.NameSpace = new System.CodeDom.CodeNamespace("XCode.Test.Entities"); //EntityClass entity = asm.Create(table); //entity.Create(); //entity.AddProperties(); //entity.AddIndexs(); //entity.AddNames(); EntityClass entity = asm.Create("Area"); String str = entity.GenerateCSharpCode(); Console.WriteLine(str); CompilerResults rs = asm.Compile(null); foreach (String item in rs.Output) { Console.WriteLine(item); } //asm.CreateAll(); //str = asm.GenerateCSharpCode(); ////File.WriteAllText(dal.ConnName + ".cs", str); //Console.WriteLine(str); }
/// <summary>从指定压缩文件恢复一批数据到目标库</summary> /// <param name="file">zip压缩文件</param> /// <param name="tables">数据表。为空时从压缩包读取xml模型文件</param> /// <param name="setSchema">是否设置数据表模型,自动建表</param> /// <returns></returns> public IDataTable[] RestoreAll(String file, IDataTable[] tables = null, Boolean setSchema = true) { if (file.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(file)); } //if (tables == null) throw new ArgumentNullException(nameof(tables)); var file2 = file.GetFullPath(); if (!File.Exists(file2)) { return(null); } using var span = Tracer?.NewSpan("db:RestoreAll", file); using var fs = new FileStream(file2, FileMode.Open); using var zip = new ZipArchive(fs, ZipArchiveMode.Read, true, Encoding.UTF8); // 备份架构 if (tables == null) { var entry = zip.Entries.FirstOrDefault(e => e.Name.EndsWithIgnoreCase(".xml")); if (entry != null) { using var ms = entry.Open(); tables = DAL.Import(ms.ToStr()).ToArray(); } } WriteLog("恢复[{0}]从文件 {1}。数据表:{2}", Dal.ConnName, file2, tables?.Join(",", e => e.Name)); if (setSchema) { Dal.SetTables(tables); } try { foreach (var item in tables) { var entry = zip.GetEntry(item.Name + ".table"); if (entry != null && entry.Length > 0) { try { using var ms = entry.Open(); using var bs = new BufferedStream(ms); Restore(bs, item); } catch (Exception ex) { if (!IgnoreError) { throw; } XTrace.WriteException(ex); } } } } catch (Exception ex) { span?.SetError(ex, null); throw; } return(tables); }
/// <summary>同步单表数据</summary> /// <remarks> /// 把数据同一张表同步到另一个库 /// </remarks> /// <param name="table">数据表</param> /// <param name="connName">目标连接名</param> /// <param name="syncSchema">同步架构</param> /// <returns></returns> public virtual Int32 Sync(IDataTable table, String connName, Boolean syncSchema = true) { if (connName.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(connName)); } if (table == null) { throw new ArgumentNullException(nameof(table)); } using var span = Tracer?.NewSpan("db:Sync", $"{table.Name}->{connName}"); var dal = DAL.Create(connName); var writeDb = new WriteDbActor { Table = table, Dal = dal, IgnorePageError = IgnorePageError, Log = Log, Tracer = Tracer, // 最多同时堆积数页 BoundedCapacity = 4, TracerParent = span, }; var extracer = GetExtracter(table); // 临时关闭日志 var old = Dal.Db.ShowSQL; Dal.Db.ShowSQL = false; Dal.Session.ShowSQL = false; var total = 0; var sw = Stopwatch.StartNew(); try { // 表结构 if (syncSchema) { dal.SetTables(table); } foreach (var dt in extracer.Fetch()) { var row = extracer.Row; var count = dt.Rows.Count; WriteLog("同步[{0}/{1}]数据 {2:n0} + {3:n0}", table.Name, Dal.ConnName, row, count); ////修复表的列名带下划线的会出现问题 //for (var i=0;i< dt.Columns.Length;i++) //{ // dt.Columns[i] = dt.Columns[i].Replace("_", ""); //} // 进度报告、消费数据 OnProcess(table, row, dt, writeDb); total += count; } // 通知写入完成 writeDb.Stop(-1); } catch (Exception ex) { span?.SetError(ex, table); throw; } finally { Dal.Db.ShowSQL = old; Dal.Session.ShowSQL = old; } sw.Stop(); var ms = sw.Elapsed.TotalMilliseconds; WriteLog("同步[{0}/{1}]完成,共[{2:n0}]行,耗时{3:n0}ms,速度{4:n0}tps", table.Name, Dal.ConnName, total, ms, total * 1000L / ms); // 返回总行数 return(total); }
/// <summary>获取提供者工厂</summary> /// <param name="assemblyFile"></param> /// <param name="className"></param> /// <param name="ignoreError"></param> /// <returns></returns> public static DbProviderFactory GetProviderFactory(String assemblyFile, String className, Boolean ignoreError = false) { try { var links = new List <String>(); var name = Path.GetFileNameWithoutExtension(assemblyFile); if (!name.IsNullOrEmpty()) { var linkName = name; #if __CORE__ if (Runtime.Linux) { linkName += Environment.Is64BitProcess ? ".linux-x64" : ".linux-x86"; links.Add(linkName); links.Add(name + ".linux"); } else { linkName += Environment.Is64BitProcess ? ".win-x64" : ".win-x86"; links.Add(linkName); links.Add(name + ".win"); } linkName = name + ".netstandard"; #else if (Environment.Is64BitProcess) { linkName += "64"; } var ver = Environment.Version; if (ver.Major >= 4) { linkName += "Fx" + ver.Major + ver.Minor; } #endif links.Add(linkName); // 有些数据库驱动不区分x86/x64,并且逐步以Fx4为主,所以来一个默认 //linkName += ";" + name; if (!links.Contains(name)) { links.Add(name); } #if __CORE__ //linkName = "st_" + name; // 指定完全类型名可获取项目中添加了引用的类型,否则dll文件需要放在根目录 className = className + "," + name; #endif } var type = PluginHelper.LoadPlugin(className, null, assemblyFile, links.Join(",")); // 反射实现获取数据库工厂 var file = assemblyFile; var plugin = NewLife.Setting.Current.GetPluginPath(); file = plugin.CombinePath(file); // 如果还没有,就写异常 if (type == null) { if (assemblyFile.IsNullOrEmpty()) { return(null); } if (!File.Exists(file)) { throw new FileNotFoundException("缺少文件" + file + "!", file); } } if (type == null) { XTrace.WriteLine("驱动文件{0}无效或不适用于当前环境,准备删除后重新下载!", assemblyFile); try { File.Delete(file); } catch (UnauthorizedAccessException) { } catch (Exception ex) { XTrace.Log.Error(ex.ToString()); } type = PluginHelper.LoadPlugin(className, null, file, links.Join(",")); // 如果还没有,就写异常 if (!File.Exists(file)) { throw new FileNotFoundException("缺少文件" + file + "!", file); } } if (type == null) { return(null); } var asm = type.Assembly; if (DAL.Debug) { DAL.WriteLog("{2}驱动{0} 版本v{1}", asm.Location, asm.GetName().Version, name ?? className.TrimEnd("Client", "Factory")); } var field = type.GetFieldEx("Instance"); if (field == null) { return(Activator.CreateInstance(type) as DbProviderFactory); } return(Reflect.GetValue(null, field) as DbProviderFactory); } catch { if (ignoreError) { return(null); } throw; } }
/// <summary>备份一批表到指定压缩文件</summary> /// <param name="tables">数据表集合</param> /// <param name="file">zip压缩文件</param> /// <param name="backupSchema">备份架构</param> /// <returns></returns> public Int32 BackupAll(IList <IDataTable> tables, String file, Boolean backupSchema = true) { if (tables == null) { throw new ArgumentNullException(nameof(tables)); } using var span = Tracer?.NewSpan("db:BackupAll", file); // 过滤不存在的表 var ts = Dal.Tables.Select(e => e.TableName).ToArray(); tables = tables.Where(e => e.TableName.EqualIgnoreCase(ts)).ToList(); var connName = Dal.ConnName; var count = 0; //if (tables == null) tables = Tables; if (tables.Count > 0) { var file2 = file.GetFullPath(); file2.EnsureDirectory(true); WriteLog("备份[{0}]到文件 {1}。{2}", connName, file2, tables.Join(",", e => e.Name)); using var fs = new FileStream(file2, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); using var zip = new ZipArchive(fs, ZipArchiveMode.Create, true, Encoding.UTF8); try { // 备份架构 if (backupSchema) { var xml = DAL.Export(tables); var entry = zip.CreateEntry(connName + ".xml"); using var ms = entry.Open(); ms.Write(xml.GetBytes()); } foreach (var item in tables) { try { var entry = zip.CreateEntry(item.Name + ".table"); using var ms = entry.Open(); Backup(item, ms); count++; } catch (Exception ex) { if (!IgnoreError) { throw; } XTrace.WriteException(ex); } } } catch (Exception ex) { span?.SetError(ex, null); throw; } } return(count); }
/// <summary>获取提供者工厂</summary> /// <param name="assemblyFile"></param> /// <param name="className"></param> /// <param name="strict"></param> /// <param name="ignoreError"></param> /// <returns></returns> public static DbProviderFactory GetProviderFactory(String assemblyFile, String className, Boolean strict = false, Boolean ignoreError = false) { try { var links = new List <String>(); var name = Path.GetFileNameWithoutExtension(assemblyFile); if (!name.IsNullOrEmpty()) { var linkName = name; #if __CORE__ var arch = (RuntimeInformation.OSArchitecture + "").ToLower(); // 可能是在x64架构上跑x86 if (arch == "x64" && !Environment.Is64BitProcess) { arch = "x86"; } var platform = ""; if (Runtime.Linux) { platform = "linux"; } else if (Runtime.OSX) { platform = "osx"; } else { platform = "win"; } links.Add($"{name}.{platform}"); links.Add($"{name}.{platform}-{arch}"); #else if (Environment.Is64BitProcess) { linkName += "64"; } var ver = Environment.Version; if (ver.Major >= 4) { linkName += "Fx" + ver.Major + ver.Minor; } links.Add(linkName); #endif // 有些数据库驱动不区分x86/x64,并且逐步以Fx4为主,所以来一个默认 if (!strict && !links.Contains(name)) { links.Add(name); } } var type = PluginHelper.LoadPlugin(className, null, assemblyFile, links.Join(",")); // 反射实现获取数据库工厂 var file = assemblyFile; var plugin = NewLife.Setting.Current.GetPluginPath(); file = plugin.CombinePath(file); // 如果还没有,就写异常 if (type == null) { if (assemblyFile.IsNullOrEmpty()) { return(null); } if (!File.Exists(file)) { throw new FileNotFoundException("缺少文件" + file + "!", file); } } if (type == null) { XTrace.WriteLine("驱动文件{0}无效或不适用于当前环境,准备删除后重新下载!", assemblyFile); try { File.Delete(file); } catch (UnauthorizedAccessException) { } catch (Exception ex) { XTrace.Log.Error(ex.ToString()); } type = PluginHelper.LoadPlugin(className, null, file, links.Join(",")); // 如果还没有,就写异常 if (!File.Exists(file)) { throw new FileNotFoundException("缺少文件" + file + "!", file); } } if (type == null) { return(null); } var asm = type.Assembly; if (DAL.Debug) { DAL.WriteLog("{2}驱动{0} 版本v{1}", asm.Location, asm.GetName().Version, name ?? className.TrimEnd("Client", "Factory")); } var field = type.GetFieldEx("Instance"); if (field == null) { return(Activator.CreateInstance(type) as DbProviderFactory); } return(Reflect.GetValue(null, field) as DbProviderFactory); } catch { if (ignoreError) { return(null); } throw; } }
DataTable GetSchemaInternal(String key, String collectionName, String[] restrictionValues) { QueryTimes++; // 如果启用了事务保护,这里要新开一个连接,否则MSSQL里面报错,SQLite不报错,其它数据库未测试 var isTrans = TransactionCount > 0; DbConnection conn = null; if (isTrans) { conn = Factory.CreateConnection(); checkConnStr(); conn.ConnectionString = ConnectionString; conn.Open(); } else { if (!Opened) { Open(); } conn = Conn; } try { DataTable dt; var sw = new Stopwatch(); sw.Start(); if (restrictionValues == null || restrictionValues.Length < 1) { if (String.IsNullOrEmpty(collectionName)) { WriteSQL("[" + Database.ConnName + "]GetSchema"); if (conn.State != ConnectionState.Closed) //ahuang 2013。06。25 当数据库连接字符串有误 { dt = conn.GetSchema(); } else { dt = null; } } else { WriteSQL("[" + Database.ConnName + "]GetSchema(\"" + collectionName + "\")"); if (conn.State != ConnectionState.Closed) { dt = conn.GetSchema(collectionName); } else { dt = null; } } } else { var sb = new StringBuilder(); foreach (var item in restrictionValues) { sb.Append(", "); if (item == null) { sb.Append("null"); } else { sb.AppendFormat("\"{0}\"", item); } } WriteSQL("[" + Database.ConnName + "]GetSchema(\"" + collectionName + "\"" + sb + ")"); if (conn.State != ConnectionState.Closed) { dt = conn.GetSchema(collectionName, restrictionValues); } else { dt = null; } } sw.Stop(); // 耗时超过多少秒输出错误日志 if (sw.ElapsedMilliseconds > 1000) { DAL.WriteLog("耗时 {0:n0}ms", sw.ElapsedMilliseconds); } return(dt); } catch (DbException ex) { throw new XDbSessionException(this, "取得所有表构架出错!", ex); } finally { if (isTrans) { conn.Close(); } else { AutoClose(); } } }
/// <summary>输出日志</summary> /// <param name="format"></param> /// <param name="args"></param> public static void WriteLog(String format, params Object[] args) { DAL.WriteLog(format, args); }
/// <summary>输出日志</summary> /// <param name="msg"></param> public static void WriteLog(String msg) { DAL.WriteLog(msg); }
DataTable GetSchemaInternal(String key, String collectionName, String[] restrictionValues) { QueryTimes++; // 如果启用了事务保护,这里要新开一个连接,否则MSSQL里面报错,SQLite不报错,其它数据库未测试 var isTrans = TransactionCount > 0; DbConnection conn; if (isTrans) { try { conn = Factory.CreateConnection(); conn.ConnectionString = ConnectionString; conn.Open(); } catch (DbException ex) { DAL.WriteLog("错误的连接字符串:{0}", ConnectionString); throw new XDbSessionException(this, "取得所有表构架出错!连接字符串有问题,请查看日志!", ex); } } else { if (!Opened) { Open(); } conn = Conn; } try { DataTable dt; if (restrictionValues == null || restrictionValues.Length < 1) { if (String.IsNullOrEmpty(collectionName)) { WriteSQL("GetSchema"); dt = conn.GetSchema(); } else { WriteSQL("GetSchema(\"" + collectionName + "\")"); dt = conn.GetSchema(collectionName); } } else { var sb = new StringBuilder(); foreach (var item in restrictionValues) { sb.Append(", "); if (item == null) { sb.Append("null"); } else { sb.AppendFormat("\"{0}\"", item); } } WriteSQL("GetSchema(\"" + collectionName + "\"" + sb + ")"); dt = conn.GetSchema(collectionName, restrictionValues); } return(dt); } catch (DbException ex) { throw new XDbSessionException(this, "取得所有表构架出错!", ex); } finally { if (isTrans) { conn.Close(); } else { AutoClose(); } } }