using System; using System.Collections.Generic; using System.Text; using CYQ.Data.Tool; using System.Threading; using System.IO; namespace CYQ.Data { /// /// 数据库类型操作类 /// internal class DalCreate { private const string SqlClient = "System.Data.SqlClient"; private const string OleDb = "System.Data.OleDb"; private const string OracleClient = "System.Data.OracleClient"; private const string SQLiteClient = "System.Data.SQLite"; private const string MySqlClient = "MySql.Data.MySqlClient"; private const string SybaseClient = "Sybase.Data.AseClient"; private const string PostgreClient = "System.Data.NpgSqlClient"; private const string TxtClient = "CYQ.Data.TxtClient"; private const string XmlClient = "CYQ.Data.XmlClient"; private const string XHtmlClient = "CYQ.Data.XHtmlClient"; /// /// 简单工厂(Factory Method) /// /// /// public static DbBase CreateDal(string dbConn) { DbBase db = GetDbBaseBy(GetConnObject(dbConn)); if (db.connObject.Master.ConfigName != dbConn && dbConn.EndsWith("Conn"))//需要切换配置。 { DbResetResult result = db.ChangeDatabase(dbConn.Substring(0, dbConn.Length - 4)); if (result == DbResetResult.Yes) // 写入缓存 { if (!connDicCache.ContainsKey(dbConn)) { connDicCache.Set(dbConn, db.connObject); } } } return db; //ConnEntity cEntity = GetConnString(dbConn); //DbBase db = GetDbBaseBy(cEntity.Conn, cEntity.ProviderName); //db.connObject = cEntity; //return db; } public static DalType GetDalTypeByConn(string conn) { return GetConnBean(conn).ConnDalType; } public static DalType GetDalTypeByReaderName(string typeName) { switch (typeName.Replace("DataReader", "").ToLower()) { case "oracle": return DalType.Oracle; case "sql": return DalType.MsSql; case "sqlite": return DalType.SQLite; case "oledb": return DalType.Access; case "mysql": return DalType.MySql; case "odbc": case "ase": return DalType.Sybase; case "PgSql": case "Npgsql": return DalType.PostgreSQL; default: return DalType.None; } } public static string GetProvider(string connString) { connString = connString.ToLower().Replace(" ", "");//去掉空格 if (connString.Contains("initialcatalog=") || connString.Contains("port=1433")) { return SqlClient; } else if (connString.Contains("microsoft.jet.oledb.4.0") || connString.Contains("microsoft.ace.oledb") || connString.Contains(".mdb")) { return OleDb; } else if (connString.Contains("provider=msdaora") || connString.Contains("provider=oraoledb.oracle") || connString.Contains("description=") || connString.Contains("fororacle")) { return OracleClient; } else if (connString.Contains("failifmissing=") || (connString.StartsWith("datasource=") && connString.EndsWith(".db"))) { return SQLiteClient; } else if (connString.Contains("convertzerodatetime") || (connString.Contains("host=") && connString.Contains("port=") && connString.Contains("database="))) { return MySqlClient; } else if (connString.Contains("provider=ase") || (connString.Contains("datasource=") && connString.Contains("port=") && connString.Contains("database="))) { return SybaseClient; } else if (connString.Contains("port=5432")) { return PostgreClient; } else if (connString.Contains("txtpath=")) { return TxtClient; } else if (connString.Contains("xmlpath=")) { return XmlClient; } else { //postgre和mssql的链接语句一样,这里用database=和uid=顺序来决定;database写在后面的,为postgre int dbIndex = connString.IndexOf("database=", StringComparison.OrdinalIgnoreCase); int uid = connString.IndexOf("uid=", StringComparison.OrdinalIgnoreCase); if (uid > 0 && uid < dbIndex && File.Exists(AppConfig.RunPath + "Npgsql.dll")) { return PostgreClient; } return SqlClient; } } public static DalType GetDalType(string providerName) { switch (providerName) { case SqlClient: return DalType.MsSql; case OleDb: return DalType.Access; case OracleClient: return DalType.Oracle; case SQLiteClient: return DalType.SQLite; case MySqlClient: return DalType.MySql; case SybaseClient: return DalType.Sybase; case PostgreClient: return DalType.PostgreSQL; case TxtClient: return DalType.Txt; case XmlClient: return DalType.Xml; } return (DalType)Error.Throw(string.Format("GetDalType:{0} No Be Support Now!", providerName)); } private static DbBase GetDbBaseBy(ConnObject co) { string providerName = co.Master.ProviderName; //License.Check(providerName);//框架模块授权检测。 switch (providerName) { case SqlClient: return new MsSqlDal(co); case OleDb: return new OleDbDal(co); case OracleClient: return new OracleDal(co); case SQLiteClient: return new SQLiteDal(co); case MySqlClient: return new MySQLDal(co); case SybaseClient: return new SybaseDal(co); case PostgreClient: return new PostgreDal(co); case TxtClient: case XmlClient: return new NoSqlDal(co); } return (DbBase)Error.Throw(string.Format("GetHelper:{0} No Be Support Now!", providerName)); } #region 注释的代码 /* private static MDictionary connCache = new MDictionary(); internal static ConnEntity GetConnString(string dbConn) // 思考备份链接的问题。=》下一步思考读写分离的问题。 { if (connCache.ContainsKey(dbConn)) { return connCache[dbConn]; } ConnEntity cEntity = new ConnEntity(); cEntity.Conn = string.IsNullOrEmpty(dbConn) ? AppConfig.DB.DefaultConn : dbConn; if (cEntity.Conn.Length < 32 && cEntity.Conn.Split(' ').Length == 1)//配置项 { if (ConfigurationManager.ConnectionStrings[cEntity.Conn] == null && cEntity.Conn != AppConfig.DB.DefaultConn) { cEntity.Conn = AppConfig.DB.DefaultConn;//转取默认配置; if (cEntity.Conn.Length >= 32 || cEntity.Conn.Trim().Contains(" ")) { goto er; } } if (ConfigurationManager.ConnectionStrings[cEntity.Conn] != null) { string p = string.Empty, c = string.Empty; #region 获取备份链接 string bakKey = cEntity.Conn + "_Bak"; if (ConfigurationManager.ConnectionStrings[cEntity.Conn + "_Bak"] == null && cEntity.Conn == AppConfig.DB.DefaultConn && AppConfig.DB.DefaultConnBak != cEntity.Conn + "_Bak") { bakKey = AppConfig.DB.DefaultConnBak; } string connBak = AppConfig.GetConn(bakKey, out p); if (connBak.Length >= 32 || connBak.Trim().Contains(" "))//如果有完整的数据库链接 { cEntity.ConnBak = AppConfig.GetConn(bakKey, out p); cEntity.ProviderNameBak = p; } #endregion cEntity.Conn = AppConfig.GetConn(cEntity.Conn, out p); cEntity.ProviderName = p; } else { Error.Throw(string.Format("Can't find the connection key '{0}' from web.config!", cEntity.Conn)); } } else if (cEntity.Conn == AppConfig.DB.DefaultConn && string.IsNullOrEmpty(cEntity.ConnBak)) { string connBak = AppConfig.GetConn(AppConfig.DB.DefaultConnBak);//先赋默认备份值。 if (connBak.Length >= 32 || connBak.Trim().Contains(" "))//如果有完整的数据库链接 { cEntity.ConnBak = connBak; } } er: if (string.IsNullOrEmpty(cEntity.ProviderName)) { cEntity.ProviderName = GetProvider(cEntity.Conn); cEntity.ConnDalType = GetDalType(cEntity.ProviderName); } if (string.IsNullOrEmpty(cEntity.ProviderNameBak) && !string.IsNullOrEmpty(cEntity.ConnBak)) { cEntity.ProviderNameBak = DalCreate.GetProvider(cEntity.ConnBak); cEntity.ConnBakDalType = GetDalType(cEntity.ProviderNameBak); } cEntity.Conn = string.Format(cEntity.Conn, AppConfig.WebRootPath); cEntity.ConnBak = string.Format(cEntity.ConnBak ?? string.Empty, AppConfig.WebRootPath); if (!connCache.ContainsKey(dbConn)) { connCache.Set(dbConn, cEntity); } return cEntity; } */ #endregion internal static string FormatConn(DalType dal, string connString) { if (dal != DalType.Access) { string conn = connString.ToLower(); int index = conn.IndexOf("provider"); if (index > -1 && index < connString.Length - 5 && (connString[index + 8] == '=' || connString[index + 9] == '=')) { int end = conn.IndexOf(';', index); if (end > index) { connString = connString.Remove(index, end - index + 1); } } } return connString; } /// /// 所有链接的对象集合 /// private static MDictionary connDicCache = new MDictionary(StringComparer.OrdinalIgnoreCase); internal static ConnObject GetConnObject(string dbConn) { dbConn = string.IsNullOrEmpty(dbConn) ? AppConfig.DB.DefaultConn : dbConn; if (dbConn.EndsWith("_Bak")) { dbConn = dbConn.Replace("_Bak", ""); } if (connDicCache.ContainsKey(dbConn)) { return connDicCache[dbConn]; } ConnBean cbMaster = GetConnBean(dbConn); if (cbMaster == null) { string errMsg = string.Format("Can't find the connection key '{0}' from web.config or app.config!", dbConn); if (dbConn == AppConfig.DB.DefaultConn) { Error.Throw(errMsg); } else { ConnBean cb = GetConnBean(AppConfig.DB.DefaultConn); if (cb != null) { cbMaster = cb.Clone();//获取默认的值。 } else { Error.Throw(errMsg); } } } ConnObject co = new ConnObject(); co.Master = cbMaster; if (dbConn != null && dbConn.Length < 32 && !dbConn.Trim().Contains(" ")) // 为configKey { ConnBean coBak = GetConnBean(dbConn + "_Bak"); if (coBak != null && coBak.ProviderName == cbMaster.ProviderName) { co.BackUp = coBak; } for (int i = 1; i < 1000; i++) { ConnBean cbSlave = GetConnBean(dbConn + "_Slave" + i); if (cbSlave == null) { break; } cbSlave.IsSlave = true; co.Slave.Add(cbSlave); } } if (!connDicCache.ContainsKey(dbConn) && co.Master.ConfigName == dbConn) // 非一致的,由外面切换后再缓存 { connDicCache.Set(dbConn, co); } return co; } private static ConnBean GetConnBean(string dbConn) { string provider; string conn = string.Format(AppConfig.GetConn(dbConn, out provider), AppConfig.WebRootPath); if (string.IsNullOrEmpty(conn)) { return null; } ConnBean cb = new ConnBean(); cb.ConfigName = dbConn; cb.Conn = conn; if (string.IsNullOrEmpty(provider)) { provider = GetProvider(cb.Conn); } cb.ProviderName = provider; cb.ConnDalType = GetDalType(provider); return cb; } /// /// 定时检测异常的链接是否恢复。 /// /// public static void CheckConnIsOk(object threadID) { while (true) { Thread.Sleep(3000); if (connDicCache.Count > 0) { try { string[] items = new string[connDicCache.Count]; connDicCache.Keys.CopyTo(items, 0); foreach (string key in items) { ConnObject obj = connDicCache[key]; if (obj != null) { if (!obj.Master.IsOK) { obj.Master.TryTestConn(); } if (obj.BackUp != null && !obj.BackUp.IsOK) { obj.BackUp.TryTestConn(); } if (obj.Slave != null && obj.Slave.Count > 0) { for (int i = 0; i < obj.Slave.Count; i++) { if (!obj.Slave[i].IsOK) { obj.Slave[i].TryTestConn(); } } } } } items = null; } catch { } } } } } }