414 lines
16 KiB
C#
414 lines
16 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Text;
|
|||
|
|
using CYQ.Data.Tool;
|
|||
|
|
using System.Threading;
|
|||
|
|
using System.IO;
|
|||
|
|
|
|||
|
|
|
|||
|
|
namespace CYQ.Data
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// <20><><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
/// </summary>
|
|||
|
|
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";
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// <20><EFBFBD><F2B5A5B9><EFBFBD><EFBFBD><EFBFBD>Factory Method<6F><64>
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="dbConn"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public static DbBase CreateDal(string dbConn)
|
|||
|
|
{
|
|||
|
|
DbBase db = GetDbBaseBy(GetConnObject(dbConn));
|
|||
|
|
if (db.connObject.Master.ConfigName != dbConn && dbConn.EndsWith("Conn"))//<2F><>Ҫ<EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD>á<EFBFBD>
|
|||
|
|
{
|
|||
|
|
DbResetResult result = db.ChangeDatabase(dbConn.Substring(0, dbConn.Length - 4));
|
|||
|
|
if (result == DbResetResult.Yes) // д<>뻺<EFBFBD><EBBBBA>
|
|||
|
|
{
|
|||
|
|
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(" ", "");//ȥ<><C8A5><EFBFBD>ո<EFBFBD>
|
|||
|
|
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<72><65>mssql<71><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>database=<3D><>uid=˳<><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>databaseд<65>ں<EFBFBD><DABA><EFBFBD><EFBFBD>ģ<EFBFBD>Ϊ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);//<2F><><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD>⡣
|
|||
|
|
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 ע<EFBFBD>͵Ĵ<EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
/*
|
|||
|
|
private static MDictionary<string, ConnEntity> connCache = new MDictionary<string, ConnEntity>();
|
|||
|
|
|
|||
|
|
|
|||
|
|
internal static ConnEntity GetConnString(string dbConn) // ˼<><CBBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD>⡣=<3D><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>˼<EFBFBD><CBBC><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣
|
|||
|
|
{
|
|||
|
|
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)//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
{
|
|||
|
|
if (ConfigurationManager.ConnectionStrings[cEntity.Conn] == null && cEntity.Conn != AppConfig.DB.DefaultConn)
|
|||
|
|
{
|
|||
|
|
cEntity.Conn = AppConfig.DB.DefaultConn;//תȡĬ<C8A1><C4AC><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
|
|||
|
|
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 <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
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(" "))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
{
|
|||
|
|
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);//<2F>ȸ<EFBFBD>Ĭ<EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD>ֵ<EFBFBD><D6B5>
|
|||
|
|
if (connBak.Length >= 32 || connBak.Trim().Contains(" "))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
{
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵĶ<D3B5><C4B6><EFBFBD>
|
|||
|
|
/// </summary>
|
|||
|
|
private static MDictionary<string, ConnObject> connDicCache = new MDictionary<string, ConnObject>(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();//<2F><>ȡĬ<C8A1>ϵ<EFBFBD>ֵ<EFBFBD><D6B5>
|
|||
|
|
}
|
|||
|
|
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) // <20><>һ<EFBFBD>µģ<C2B5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD>ٻ<EFBFBD><D9BB><EFBFBD>
|
|||
|
|
{
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ָ<EFBFBD><D6B8><EFBFBD>
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="threadID"></param>
|
|||
|
|
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
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|