增强MySql兼容性,修正一些小BUG
nnhy authored at 2016-04-02 16:41:43
9.75 KiB
X
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using NewLife;
using NewLife.Collections;
using NewLife.Reflection;

namespace XCode.DataAccessLayer
{
    /// <summary>数据库元数据</summary>
    abstract partial class DbMetaData : DisposeBase, IMetaData
    {
        #region 属性
        private IDatabase _Database;
        /// <summary>数据库</summary>
        public virtual IDatabase Database { get { return _Database; } set { _Database = value; } }

        private ICollection<String> _MetaDataCollections;
        /// <summary>所有元数据集合</summary>
        public ICollection<String> MetaDataCollections
        {
            get
            {
                if (_MetaDataCollections == null)
                {
                    var list = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
                    var dt = GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null);
                    if (dt != null && dt.Rows != null && dt.Rows.Count > 0)
                    {
                        foreach (DataRow dr in dt.Rows)
                        {
                            String name = "" + dr[0];
                            if (!String.IsNullOrEmpty(name) && !list.Contains(name)) list.Add(name);
                        }
                    }
                    _MetaDataCollections = list;
                }
                return _MetaDataCollections;
            }
        }

        private ICollection<String> _ReservedWords;
        /// <summary>保留关键字</summary>
        public virtual ICollection<String> ReservedWords
        {
            get
            {
                if (_ReservedWords == null)
                {
                    var list = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
                    if (MetaDataCollections.Contains(DbMetaDataCollectionNames.ReservedWords))
                    {
                        var dt = GetSchema(DbMetaDataCollectionNames.ReservedWords, null);
                        if (dt != null && dt.Rows != null && dt.Rows.Count > 0)
                        {
                            foreach (DataRow dr in dt.Rows)
                            {
                                String name = "" + dr[0];
                                if (!String.IsNullOrEmpty(name) && !list.Contains(name)) list.Add(name);
                            }
                        }
                    }
                    _ReservedWords = list;
                }
                return _ReservedWords;
            }
        }

        //String _ParamPrefix;
        ///// <summary>参数前缀</summary>
        //public String ParamPrefix
        //{
        //    get
        //    {
        //        if (_ParamPrefix == null)
        //        {
        //            var dt = GetSchema(DbMetaDataCollectionNames.DataSourceInformation, null);
        //            if (dt != null && dt.Rows != null && dt.Rows.Count > 0)
        //            {
        //                String str = null;
        //                if (TryGetDataRowValue<String>(dt.Rows[0], DbMetaDataColumnNames.ParameterMarkerPattern, out str) ||
        //                    TryGetDataRowValue<String>(dt.Rows[0], DbMetaDataColumnNames.ParameterMarkerFormat, out str))
        //                    _ParamPrefix = str.StartsWith("\\") ? str.Substring(1, 1) : str.Substring(0, 1);
        //            }

        //            if (_ParamPrefix == null) _ParamPrefix = "";
        //        }
        //        return _ParamPrefix;
        //    }
        //}
        #endregion

        #region GetSchema方法
        /// <summary>返回数据源的架构信息</summary>
        /// <param name="collectionName">指定要返回的架构的名称。</param>
        /// <param name="restrictionValues">为请求的架构指定一组限制值。</param>
        /// <returns></returns>
        public DataTable GetSchema(string collectionName, string[] restrictionValues)
        {
            // 如果不是MetaDataCollections,并且MetaDataCollections中没有该集合,则返回空
            if (!collectionName.EqualIgnoreCase(DbMetaDataCollectionNames.MetaDataCollections))
            {
                if (!MetaDataCollections.Contains(collectionName)) return null;
            }
            return Database.CreateSession().GetSchema(collectionName, restrictionValues);
        }
        #endregion

        #region 辅助函数
        /// <summary>尝试从指定数据行中读取指定名称列的数据</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <param name="name">名称</param>
        /// <param name="value">数值</param>
        /// <returns></returns>
        protected static Boolean TryGetDataRowValue<T>(DataRow dr, String name, out T value)
        {
            value = default(T);
            if (dr == null || !dr.Table.Columns.Contains(name) || dr.IsNull(name)) return false;

            Object obj = dr[name];

            // 特殊处理布尔类型
            if (Type.GetTypeCode(typeof(T)) == TypeCode.Boolean && obj != null)
            {
                if (obj is Boolean)
                {
                    value = (T)obj;
                    return true;
                }

                if ("YES".EqualIgnoreCase(obj.ToString()))
                {
                    value = (T)(Object)true;
                    return true;
                }
                if ("NO".EqualIgnoreCase(obj.ToString()))
                {
                    value = (T)(Object)false;
                    return true;
                }
            }

            try
            {
                if (obj is T)
                    value = (T)obj;
                else
                {
                    if (obj != null)
                    {
                        var tx = TypeX.Create(obj.GetType());
                        if (tx.IsInt)
                        {
                            var n = Convert.ToUInt64(obj);
                            if (n == UInt32.MaxValue && Type.GetTypeCode(typeof(T)) == TypeCode.Int32)
                            {
                                obj = -1;
                            }
                        }
                    }
                    value = (T)Reflect.ChangeType(obj, typeof(T));
                }
            }
            catch { return false; }

            return true;
        }

        /// <summary>获取指定数据行指定字段的值,不存在时返回空</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <param name="name">名称</param>
        /// <returns></returns>
        protected static T GetDataRowValue<T>(DataRow dr, String name)
        {
            T value = default(T);
            if (TryGetDataRowValue<T>(dr, name, out value)) return value;
            return default(T);
        }

        /// <summary>格式化关键字</summary>
        /// <param name="name">名称</param>
        /// <returns></returns>
        protected String FormatName(String name)
        {
            //return Database.FormatKeyWord(keyWord);
            return Database.FormatName(name);
        }

        /// <summary>检查并获取当前数据库的默认值。如果数据库类型一致,则直接返回false,因为没有修改</summary>
        /// <param name="dc"></param>
        /// <param name="oriDefault"></param>
        /// <returns></returns>
        protected virtual Boolean CheckAndGetDefault(IDataColumn dc, ref String oriDefault)
        {
            // 如果数据库类型等于原始类型,则直接通过
            if (dc.Table.DbType == Database.DbType) return false;

            // 原始数据库类型
            var db = DbFactory.Create(dc.Table.DbType);
            if (db == null) return false;

            var tc = Type.GetTypeCode(dc.DataType);
            // 特殊处理时间
            if (tc == TypeCode.DateTime)
            {
                if (String.IsNullOrEmpty(oriDefault) || oriDefault.EqualIgnoreCase(db.DateTimeNow))
                {
                    oriDefault = Database.DateTimeNow;
                    return true;
                }
                else
                {
                    //// 出现了不支持的时间默认值
                    //if (DAL.Debug) DAL.WriteLog("出现了{0}不支持的时间默认值:{1}.{2}={3}", Database.DbType, dc.Table.Name, dc.Name, oriDefault);

                    //oriDefault = null;
                    //return true;

                    return false;
                }
            }
            // 特殊处理Guid
            else if (tc == TypeCode.String || dc.DataType == typeof(Guid))
            {
                // 如果字段类型是Guid,不需要设置默认值,则也说明是Guid字段
                if (String.IsNullOrEmpty(oriDefault) || oriDefault.EqualIgnoreCase(db.NewGuid) ||
                   String.IsNullOrEmpty(db.NewGuid) && dc.DataType == typeof(Guid))
                {
                    oriDefault = Database.NewGuid;
                    return true;
                }
            }

            return false;
        }
        #endregion

        #region 日志输出
        /// <summary>输出日志</summary>
        /// <param name="msg"></param>
        public static void WriteLog(String msg) { DAL.WriteLog(msg); }

        /// <summary>输出日志</summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        public static void WriteLog(String format, params Object[] args) { DAL.WriteLog(format, args); }
        #endregion
    }
}