310 lines
11 KiB
C#
310 lines
11 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
|
||
using Zhaizj.Framework.ORM;
|
||
using Zhaizj.Framework.Reflection;
|
||
using Zhaizj.Framework.Serialization;
|
||
using Zhaizj.Framework.Web;
|
||
using System.IO;
|
||
using System.Web;
|
||
using Zhaizj.Framework.IO;
|
||
using Zhaizj.Framework.Data.Config;
|
||
|
||
namespace Zhaizj.Framework.Data {
|
||
|
||
/// <summary>
|
||
/// 数据库连接字符串内容的封装
|
||
/// </summary>
|
||
public class ConnectionString {
|
||
public String Name { get; set; }
|
||
public String StringContent { get; set; }
|
||
public DatabaseType DbType { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// ORM 的数据库配置
|
||
/// </summary>
|
||
public class DbConfig {
|
||
|
||
private static readonly ILog logger = LogManager.GetLogger( typeof( DbConfig ) );
|
||
|
||
public DbConfig() {
|
||
this.ConnectionStringTable = new Dictionary<String, object>();
|
||
this.AssemblyList = new List<object>();
|
||
this.DbType = new Dictionary<String, object>();
|
||
this.IdType = Zhaizj.Framework.Data.IdType.Auto;
|
||
this.Interceptor = new List<object>();
|
||
this.IsCheckDatabase = true;
|
||
this.ContextCache = true;
|
||
this.Mapping = new List<object>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 默认数据库名称(值为default)
|
||
/// </summary>
|
||
public static readonly String DefaultDbName = "default";
|
||
|
||
/// <summary>
|
||
/// 配置的缓存内容(单例模式缓存)
|
||
/// </summary>
|
||
public static DbConfig Instance = loadConfig( getConfigPath() );
|
||
|
||
/// <summary>
|
||
/// 直接解析json的结果:多个数据库连接字符串(connectionString)的键值对
|
||
/// </summary>
|
||
public Dictionary<String, object> ConnectionStringTable { get; set; }
|
||
|
||
private Dictionary<String, ConnectionString> _connectionStringMap = new Dictionary<String, ConnectionString>();
|
||
|
||
/// <summary>
|
||
/// 多个数据库连接字符串对象的map,值是ConnectionString对象(包括Name/StringContent/DbType)
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public Dictionary<String, ConnectionString> GetConnectionStringMap() {
|
||
return _connectionStringMap;
|
||
}
|
||
|
||
internal void SetConnectionStringMap( Dictionary<String, ConnectionString> cmap ) {
|
||
_connectionStringMap = cmap;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 直接解析json的结果:数据库类型
|
||
/// </summary>
|
||
public Dictionary<String, object> DbType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 实体键值类型
|
||
/// </summary>
|
||
public String IdType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 自动键值
|
||
/// </summary>
|
||
[NotSerialize]
|
||
public bool IsAutoId
|
||
{
|
||
get { return IdType.Equals(Zhaizj.Framework.Data.IdType.Auto, StringComparison.OrdinalIgnoreCase); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 直接解析json的结果:程序集列表
|
||
/// </summary>
|
||
public List<object> AssemblyList { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否坚持数据库,如果检查,则会将尚未创建的数据表自动创建
|
||
/// </summary>
|
||
public Boolean IsCheckDatabase { get; set; }
|
||
|
||
/// <summary>
|
||
/// 数据表的前缀(默认没有前缀)
|
||
/// </summary>
|
||
public String TablePrefix { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否开启一级缓存,默认开启,并且建议开启
|
||
/// </summary>
|
||
public Boolean ContextCache { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否开启二级缓存
|
||
/// </summary>
|
||
public Boolean ApplicationCache { get; set; }
|
||
|
||
/// <summary>
|
||
/// 二级缓存的时间(分钟)
|
||
/// </summary>
|
||
public int ApplicationCacheMinutes { get; set; }
|
||
|
||
/// <summary>
|
||
/// 二级缓存管理程序,请填写类型(type)的全名(full name),比如 Zhaizj.Framework.somens.myCache;
|
||
/// 如果不填写,则使用默认的System.Web.Caching
|
||
/// </summary>
|
||
public String ApplicationCacheManager { get; set; }
|
||
|
||
/// <summary>
|
||
/// ORM 的元数据文件名称,一般不需填写(建议不要填写)。如果为了提高网站启动时候的速度,可以填写。
|
||
/// 系统会根据文件名自动生成元数据文件,可以避免以后网站启动过程中的反射,能略微提高启动速度;
|
||
/// 文件名不包括路径(必须放在bin目录中),比如 Zhaizj.Framework.meta.dll
|
||
/// </summary>
|
||
public String MetaDLL { get; set; }
|
||
|
||
/// <summary>
|
||
/// 直接解析json的结果:数据表映射
|
||
/// </summary>
|
||
public List<object> Mapping { get; set; }
|
||
|
||
/// <summary>
|
||
/// 拦截器列表
|
||
/// </summary>
|
||
public List<object> Interceptor { get; set; }
|
||
|
||
/// <summary>
|
||
/// 反射优化模式,目前只实现了 CodeDom 方式
|
||
/// </summary>
|
||
[NotSerialize]
|
||
internal OptimizeMode OptimizeMode {
|
||
get { return OptimizeMode.CodeDom; }
|
||
set { }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取元数据库文件的绝对路径
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public String GetMetaDllAbsPath() {
|
||
|
||
if (strUtil.IsNullOrEmpty( this.MetaDLL )) return "";
|
||
|
||
String dllPath = this.MetaDLL;
|
||
if (dllPath.ToLower().EndsWith( ".dll" ) == false)
|
||
dllPath = dllPath + ".dll";
|
||
|
||
dllPath = Path.Combine( PathTool.GetBinDirectory(), dllPath );
|
||
|
||
|
||
return dllPath;
|
||
}
|
||
|
||
private Dictionary<String, MappingInfo> _mappings = new Dictionary<String, MappingInfo>();
|
||
|
||
private void addMapping( MappingInfo mi ) {
|
||
_mappings.Add( mi.TypeName, mi );
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取映射信息
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
internal Dictionary<String, MappingInfo> GetMappingInfo() {
|
||
return _mappings;
|
||
}
|
||
|
||
//----------------------------------------------------------------------
|
||
|
||
private static DbConfig loadConfig( String cfgPath ) {
|
||
|
||
String str = SectionDataHandler.Current.GetDataConfig();//file.Read( cfgPath );
|
||
DbConfig dbc = JSON.ToObject<DbConfig>( str );
|
||
|
||
loadMappingInfo( dbc );
|
||
checkConnectionString( dbc );
|
||
|
||
return dbc;
|
||
}
|
||
|
||
private static void loadMappingInfo( DbConfig dbc ) {
|
||
if (dbc.Mapping.Count == 0) return;
|
||
foreach (Dictionary<String, object> dic in dbc.Mapping) {
|
||
|
||
MappingInfo mi = new MappingInfo();
|
||
|
||
if (dic.ContainsKey( "name" )) mi.TypeName = dic["name"].ToString();
|
||
if (dic.ContainsKey( "database" )) mi.Database = dic["database"].ToString();
|
||
if (dic.ContainsKey( "table" )) mi.Table = dic["table"].ToString();
|
||
|
||
dbc.addMapping( mi );
|
||
}
|
||
}
|
||
|
||
private static String getConfigPath() {
|
||
return PathHelper.Map( strUtil.Join( cfgHelper.ConfigRoot, "orm.config" ) );
|
||
}
|
||
|
||
private static void checkConnectionString( DbConfig result ) {
|
||
|
||
logger.Info( "checkConnectionString..." );
|
||
|
||
if (result.ConnectionStringTable == null) return;
|
||
|
||
Dictionary<String, ConnectionString> connStringMap = new Dictionary<String, ConnectionString>();
|
||
|
||
Dictionary<String, String> newString = new Dictionary<string, string>();
|
||
foreach (KeyValuePair<String, object> kv in result.ConnectionStringTable) {
|
||
|
||
String connectionString = kv.Value.ToString();
|
||
DatabaseType dbtype = getDbType( kv.Key, connectionString, result );
|
||
|
||
ConnectionString objConnString = new ConnectionString {
|
||
Name = kv.Key,
|
||
StringContent = connectionString,
|
||
DbType = dbtype
|
||
};
|
||
|
||
connStringMap.Add( kv.Key, objConnString );
|
||
|
||
logger.Info( "connectionString:" + connectionString );
|
||
|
||
IDatabaseDialect dialect = DataFactory.GetDialect( dbtype );
|
||
|
||
if ((dbtype == DatabaseType.Access)) {
|
||
String connectionItem = dialect.GetConnectionItem( connectionString, ConnectionItemType.Database );
|
||
logger.Info( "database path original:" + connectionItem );
|
||
|
||
if (IsRelativePath( connectionItem )) {
|
||
connectionItem = PathHelper.Map( strUtil.Join( SystemInfo.ApplicationPath, connectionItem ) );
|
||
logger.Info( "database path now:" + connectionItem );
|
||
String newConnString = String.Format( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}", connectionItem );
|
||
|
||
newString.Add( kv.Key, newConnString );
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
foreach (KeyValuePair<String, String> kv in newString) {
|
||
result.ConnectionStringTable[kv.Key] = kv.Value;
|
||
connStringMap[kv.Key].StringContent = kv.Value;
|
||
}
|
||
|
||
result.SetConnectionStringMap( connStringMap );
|
||
}
|
||
|
||
private static bool IsRelativePath( string connectionItem ) {
|
||
return connectionItem.IndexOf( ":" ) < 0;
|
||
}
|
||
|
||
private static DatabaseType getDbType( String dbname, String connectionString, DbConfig result ) {
|
||
|
||
foreach (KeyValuePair<String, Object> kv in result.DbType) {
|
||
if (kv.Key == dbname) return DbTypeChecker.GetFromString( kv.Value.ToString() );
|
||
}
|
||
|
||
DatabaseType dbtype = DbTypeChecker.GetDatabaseType( connectionString );
|
||
return dbtype;
|
||
}
|
||
|
||
//----------------------------------------------------------------------
|
||
|
||
/// <summary>
|
||
/// 根据命名,获取数据库连接字符串
|
||
/// </summary>
|
||
/// <param name="db"></param>
|
||
/// <returns></returns>
|
||
public static String GetConnectionString( String db ) {
|
||
if (DbConfig.Instance.ConnectionStringTable.ContainsKey( db ) == false)
|
||
throw new Exception( lang.get( "dbNotExist" ) + ": " + db );
|
||
return (String)DbConfig.Instance.ConnectionStringTable[db];
|
||
}
|
||
|
||
|
||
internal static void SaveConnectionString( String connectionString ) {
|
||
|
||
String cfgPath = getConfigPath();
|
||
|
||
if (DbConfig.Instance.ConnectionStringTable == null)
|
||
DbConfig.Instance.ConnectionStringTable = new Dictionary<String, object>();
|
||
|
||
DbConfig.Instance.ConnectionStringTable[DefaultDbName] = connectionString;
|
||
|
||
String str = JsonString.ConvertObject( DbConfig.Instance, true );
|
||
|
||
file.Write( cfgPath, str );
|
||
}
|
||
|
||
}
|
||
|
||
}
|