[fix]Config创建默认配置文件的开关Runtime.CreateConfigOnMissing,仅需对自动创建生效,而不应该阻止用户主动Save
智能大石头 authored at 2024-08-09 00:30:41 石头 committed at 2024-08-10 14:22:24
34.17 KiB
X
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using NewLife.IO;
using NewLife.Reflection;

#if ACCESS
using ADODB;
using ADOX;
using DAO;
#if NET4
using ConnectionClass = ADODB.Connection;
using DBEngineClass = DAO.DBEngine;
using CatalogClass = ADOX.Catalog;
#endif
#endif

namespace XCode.DataAccessLayer
{
    class Access : FileDbBase
    {
        #region 属性
        /// <summary>返回数据库类型。外部DAL数据库类请使用Other</summary>
        public override DatabaseType DbType { get { return DatabaseType.Access; } }

        private static DbProviderFactory _dbProviderFactory;
        /// <summary>工厂</summary>
        public override DbProviderFactory Factory
        {
            get
            {
                if (_dbProviderFactory == null)
                {
                    _dbProviderFactory = OleDbFactory.Instance;

                    // 检查ADOX
#if !NET4
                    //CheckAndDownload("Interop.ADOX.dll");
#endif
                }
                return _dbProviderFactory;
            }
        }

        protected override string DefaultConnectionString
        {
            get
            {
                var builder = Factory.CreateConnectionStringBuilder();
                if (builder != null)
                {
                    var name = Path.GetTempFileName();
                    FileSource.ReleaseFile(Assembly.GetExecutingAssembly(), "Database.mdb", name, true);

                    builder[_.DataSource] = name;
                    builder["Provider"] = "Microsoft.Jet.OLEDB.4.0";
                    return builder.ToString();
                }

                return base.DefaultConnectionString;
            }
        }
        #endregion

        #region 方法
        /// <summary>创建数据库会话</summary>
        /// <returns></returns>
        protected override IDbSession OnCreateSession() { return new AccessSession(); }

        /// <summary>创建元数据对象</summary>
        /// <returns></returns>
        protected override IMetaData OnCreateMetaData() { return new AccessMetaData(); }

        public override bool Support(string providerName)
        {
            providerName = providerName.ToLower();
            if (providerName.Contains("microsoft.jet.oledb")) return true;
            if (providerName.Contains("access")) return true;
            if (providerName.Contains("oledb")) return true;

            return false;
        }

        protected override void OnSetConnectionString(XDbConnectionStringBuilder builder)
        {
            base.OnSetConnectionString(builder);

            // 特别处理一下Excel
            if (!String.IsNullOrEmpty(FileName))
            {
                String ext = Path.GetExtension(FileName);
                if (ext.EqualIgnoreCase(".xls"))
                {
                    if (!builder.ContainsKey("Extended Properties")) builder["Extended Properties"] = "Excel 8.0";
                }
            }
        }
        #endregion

        #region 数据库特性
        /// <summary>当前时间函数</summary>
        public override String DateTimeNow { get { return "now()"; } }

        /// <summary>最小时间</summary>
        public override DateTime DateTimeMin { get { return DateTime.MinValue; } }

        /// <summary>长文本长度</summary>
        public override Int32 LongTextLength { get { return 255; } }

        public override string FormatName(string name)
        {
            if (!String.IsNullOrEmpty(name) && name.Contains("$"))
                return FormatKeyWord(name);
            else
                return base.FormatName(name);
        }

        /// <summary>格式化时间为SQL字符串</summary>
        /// <param name="dateTime">时间值</param>
        /// <returns></returns>
        public override String FormatDateTime(DateTime dateTime) { return "#" + dateTime.ToFullString() + "#"; }
        //public override String FormatDateTime(DateTime dateTime)
        //{
        //    return String.Format("#{0:yyyy-MM-dd HH:mm:ss}#", dateTime);
        //}

        /// <summary>格式化关键字</summary>
        /// <param name="keyWord">关键字</param>
        /// <returns></returns>
        public override String FormatKeyWord(String keyWord)
        {
            //if (String.IsNullOrEmpty(keyWord)) throw new ArgumentNullException("keyWord");
            if (String.IsNullOrEmpty(keyWord)) return keyWord;

            if (keyWord.StartsWith("[") && keyWord.EndsWith("]")) return keyWord;

            return String.Format("[{0}]", keyWord);
            //return keyWord;
        }

        /// <summary>格式化数据为SQL数据</summary>
        /// <param name="field">字段</param>
        /// <param name="value">数值</param>
        /// <returns></returns>
        public override string FormatValue(IDataColumn field, object value)
        {
            if (field != null && field.DataType == typeof(Boolean) || value != null && value.GetType() == typeof(Boolean))
            {
                if (value == null) return field.Nullable ? "null" : "";

                return value.ToString();
            }

            return base.FormatValue(field, value);
        }
        #endregion

        #region 分页
        public override SelectBuilder PageSplit(SelectBuilder builder, int startRowIndex, int maximumRows)
        {
            return MSPageSplit.PageSplit(builder, startRowIndex, maximumRows, false, b => CreateSession().QueryCount(b));
        }
        #endregion

        #region 平台检查
        /// <summary>是否支持</summary>
        public static void CheckSupport()
        {
            Module module = typeof(Object).Module;

            PortableExecutableKinds kind;
            ImageFileMachine machine;
            module.GetPEKind(out kind, out machine);

            if (machine != ImageFileMachine.I386) throw new NotSupportedException("64位平台不支持OLEDB驱动!");
        }
        #endregion
    }

    /// <summary>Access数据库</summary>
    internal class AccessSession : FileDbSession
    {
        #region 方法
        /// <summary>打开。已重写,为了建立数据库</summary>
        public override void Open()
        {
            Access.CheckSupport();

            base.Open();
        }
        #endregion

        #region 基本方法 查询/执行
        /// <summary>执行插入语句并返回新增行的自动编号</summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="type">命令类型,默认SQL文本</param>
        /// <param name="ps">命令参数</param>
        /// <returns>新增行的自动编号</returns>
        public override Int64 InsertAndGetIdentity(String sql, CommandType type = CommandType.Text, params DbParameter[] ps)
        {
            var b = IsAutoClose;
            // 禁用自动关闭,保证两次在同一会话
            IsAutoClose = false;

            BeginTransaction();
            try
            {
                Int64 rs = Execute(sql, type, ps);
                if (rs > 0) rs = ExecuteScalar<Int64>("Select @@Identity");
                Commit();
                return rs;
            }
            catch { Rollback(true); throw; }
            finally
            {
                IsAutoClose = b;
                AutoClose();
            }
        }
        #endregion
    }

    /// <summary>Access元数据</summary>
    class AccessMetaData : FileDbMetaData
    {
        #region 构架
        protected override List<IDataTable> OnGetTables(ICollection<String> names)
        {
            var dt = GetSchema(_.Tables, null);
            if (dt == null || dt.Rows == null || dt.Rows.Count < 1) return null;

            // 默认列出所有字段
            DataRow[] rows = dt.Select(String.Format("{0}='Table' Or {0}='View'", "TABLE_TYPE"));
            rows = OnGetTables(names, rows);
            if (rows == null || rows.Length < 1) return null;

            return GetTables(rows);
        }

#if ACCESS
        protected override List<IDataColumn> GetFields(IDataTable xt)
        {
            var list = base.GetFields(xt);
            if (list == null || list.Count < 1) return null;

            var dic = new Dictionary<String, IDataColumn>(StringComparer.OrdinalIgnoreCase);
            foreach (var xf in list)
            {
                dic.Add(xf.ColumnName, xf);
            }

            try
            {
                using (var table = GetTable(xt.TableName))
                {
                    if (table.Supported && table.Columns != null)
                    {
                        foreach (var item in table.Columns)
                        {
                            if (!dic.ContainsKey(item.Name)) continue;

                            var field = dic[item.Name];
                            field.Identity = item.AutoIncrement;
                            if (!field.Identity) field.Nullable = item.Nullable;
                        }
                    }
                }
            }
            catch { }

            return list;
        }
#endif

        protected override void FixField(IDataColumn field, DataRow drColumn)
        {
            base.FixField(field, drColumn);

            // 字段标识
            Int64 flag = GetDataRowValue<Int64>(drColumn, "COLUMN_FLAGS");

            Boolean? isLong = null;

            Int32 id = 0;
            if (Int32.TryParse(GetDataRowValue<String>(drColumn, "DATA_TYPE"), out id))
            {
                DataRow[] drs = FindDataType(field, "" + id, isLong);
                if (drs != null && drs.Length > 0)
                {
                    String typeName = GetDataRowValue<String>(drs[0], "TypeName");
                    field.RawType = typeName;

                    if (TryGetDataRowValue<String>(drs[0], "DataType", out typeName)) field.DataType = typeName.GetTypeEx();

                    // 修正备注类型
                    if (field.DataType == typeof(String) && drs.Length > 1)
                    {
                        isLong = (flag & 0x80) == 0x80;
                        drs = FindDataType(field, "" + id, isLong);
                        if (drs != null && drs.Length > 0)
                        {
                            typeName = GetDataRowValue<String>(drs[0], "TypeName");
                            field.RawType = typeName;
                        }
                    }
                }
            }

            //// 处理自增
            //if (field.DataType == typeof(Int32))
            //{
            //    //field.Identity = (flag & 0x20) != 0x20;
            //}
        }

        protected override void FixField(IDataColumn field, DataRow drColumn, DataRow drDataType)
        {
            base.FixField(field, drColumn, drDataType);

            // 修正原始类型
            String typeName = null;
            if (TryGetDataRowValue<String>(drDataType, "TypeName", out typeName)) field.RawType = typeName;
        }

        protected override List<IDataIndex> GetIndexes(IDataTable table)
        {
            var list = base.GetIndexes(table);
            if (list != null && list.Count > 0)
            {
                // Access的索引直接以索引字段的方式排布,所以需要重新组合起来
                var dic = new Dictionary<String, IDataIndex>();
                foreach (var item in list)
                {
                    IDataIndex di = null;
                    if (!dic.TryGetValue(item.Name, out di))
                    {
                        dic.Add(item.Name, item);
                    }
                    else
                    {
                        var ss = new List<String>(di.Columns);
                        if (item.Columns != null && item.Columns.Length > 0 && !ss.Contains(item.Columns[0]))
                        {
                            ss.Add(item.Columns[0]);
                            di.Columns = ss.ToArray();
                        }
                    }
                }
                list.Clear();
                foreach (var item in dic.Values)
                {
                    list.Add(item);
                }
            }
            return list;
        }

        //protected override void FixIndex(IDataIndex index, DataRow dr)
        //{
        //    base.FixIndex(index, dr);

        //    Boolean b = false;
        //    if (TryGetDataRowValue<Boolean>(dr, "PRIMARY_KEY", out b)) index.PrimaryKey = b;
        //    if (TryGetDataRowValue<Boolean>(dr, "UNIQUE", out b)) index.PrimaryKey = b;
        //}

        protected override string GetFieldConstraints(IDataColumn field, Boolean onlyDefine)
        {
            String str = base.GetFieldConstraints(field, onlyDefine);

            if (field.Identity) str = " AUTOINCREMENT(1,1)" + str;

            return str;
        }

        /// <summary>取得字段默认值</summary>
        /// <param name="field">字段</param>
        /// <param name="onlyDefine">仅仅定义</param>
        /// <returns></returns>
        protected override string GetFieldDefault(IDataColumn field, bool onlyDefine)
        {
            // Access不能通过DDL来操作默认值
            return null;
        }
        #endregion

        #region 数据定义
#if ACCESS
        /// <summary>设置数据定义模式</summary>
        /// <param name="schema"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public override object SetSchema(DDLSchema schema, object[] values)
        {
            Object obj = null;
            switch (schema)
            {
                case DDLSchema.CreateTable:
                    obj = base.SetSchema(DDLSchema.CreateTable, values);
                    IDataTable table = values[0] as IDataTable;

                    // Access建表语句的不能操作默认值,所以在这里操作

                    // 默认值
                    foreach (IDataColumn item in table.Columns)
                    {
                        if (!String.IsNullOrEmpty(item.Default)) AddDefault(item, item.Default);
                    }

                    return obj;
                case DDLSchema.AddTableDescription:
                    return AddTableDescription((IDataTable)values[0], ((IDataTable)values[0]).Description);
                case DDLSchema.DropTableDescription:
                    return DropTableDescription((IDataTable)values[0]);
                case DDLSchema.AddColumnDescription:
                    return AddColumnDescription((IDataColumn)values[0], ((IDataColumn)values[0]).Description);
                case DDLSchema.DropColumnDescription:
                    return DropColumnDescription((IDataColumn)values[0]);
                case DDLSchema.AddDefault:
                    return AddDefault((IDataColumn)values[0], ((IDataColumn)values[0]).Default);
                case DDLSchema.DropDefault:
                    return DropDefault((IDataColumn)values[0]);
                default:
                    break;
            }
            return base.SetSchema(schema, values);
        }
#endif
        #endregion

        #region 创建数据库
#if ACCESS
        const string dbLangChineseSimplified = ";LANGID=0x0804;CP=936;COUNTRY=0";

        /// <summary>创建数据库</summary>
        protected override void CreateDatabase()
        {
            if (String.IsNullOrEmpty(FileName) || File.Exists(FileName)) return;

            DAL.WriteDebugLog("创建数据库:{0}", FileName);

            //FileSource.ReleaseFile(Assembly.GetExecutingAssembly(), "Database.mdb", FileName, true);

            var dbe = new DBEngineClass();
            try
            {
                var db = dbe.CreateDatabase(FileName, dbLangChineseSimplified);
                if (db != null)
                {
                    db.Close();
                    Marshal.ReleaseComObject(db);
                }
            }
            catch (Exception ex)
            {
                XTrace.WriteException(ex);
            }
            finally
            {
                Marshal.ReleaseComObject(dbe);
            }
        }
#endif
        #endregion

        #region 反向工程创建表
        protected override void CreateTable(StringBuilder sb, IDataTable table, bool onlySql)
        {
            base.CreateTable(sb, table, onlySql);

            if (!onlySql)
            {
                IDatabase entityDb = null;
                foreach (IDataColumn dc in table.Columns)
                {
                    // 如果实体存在默认值,则增加
                    if (!String.IsNullOrEmpty(dc.Default))
                    {
                        var tc = Type.GetTypeCode(dc.DataType);
                        String dv = dc.Default;
                        // 特殊处理时间
                        if (tc == TypeCode.DateTime)
                        {
                            if (entityDb != null && dv == entityDb.DateTimeNow) dc.Default = Database.DateTimeNow;
                        }
                        // 特殊处理Guid
                        else if (tc == TypeCode.String || dc.DataType == typeof(Guid))
                        {
                            if (entityDb != null && dv == entityDb.NewGuid) dc.Default = Database.NewGuid;
                        }

                        PerformSchema(sb, onlySql, DDLSchema.AddDefault, dc);

                        // 还原
                        dc.Default = dv;
                    }
                }
            }
        }

        public override string CreateTableSQL(IDataTable table)
        {
            var sql = base.CreateTableSQL(table);

            var pks = table.PrimaryKeys;
            if (String.IsNullOrEmpty(sql) || pks.Length < 2) return sql;

            // 处理多主键
            var names = pks.Select(e => e.ColumnName).ToArray();
            var di = ModelHelper.GetIndex(table, names);
            if (di == null)
            {
                di = table.CreateIndex();
                di.PrimaryKey = true;
                di.Unique = true;
                di.Columns = names;
            }
            // Access里面的主键索引名必须叫这个
            di.Name = "PrimaryKey";

            sql += ";" + Environment.NewLine;
            sql += CreateIndexSQL(di);
            return sql;
        }

        public override string CreateIndexSQL(IDataIndex index)
        {
            String sql = base.CreateIndexSQL(index);
            if (String.IsNullOrEmpty(sql) || !index.PrimaryKey) return sql;

            return sql + " WITH PRIMARY";
        }
        #endregion

        #region 表和字段备注
#if ACCESS
        public Boolean AddTableDescription(IDataTable table, String value)
        {
            try
            {
                using (var tb = GetTable(table.TableName))
                {
                    tb.Description = value;
                    return true;
                }
            }
            catch { return false; }
        }

        public Boolean DropTableDescription(IDataTable table)
        {
            return AddTableDescription(table, null);
        }

        public Boolean AddColumnDescription(IDataColumn field, String value)
        {
            try
            {
                using (var table = GetTable(field.Table.TableName))
                {
                    if (table.Supported && table.Columns != null)
                    {
                        foreach (var item in table.Columns)
                        {
                            if (item.Name == field.ColumnName)
                            {
                                item.Description = value;
                                return true;
                            }
                        }
                    }
                    return false;
                }
            }
            catch { return false; }
        }

        public Boolean DropColumnDescription(IDataColumn field)
        {
            return AddColumnDescription(field, null);
        }
#endif
        #endregion

        #region 默认值
#if ACCESS
        public virtual Boolean AddDefault(IDataColumn field, String value)
        {
            //if (field.DataType == typeof(DateTime))
            //{
            CheckAndGetDefault(field, ref value);
            //}

            try
            {
                using (var table = GetTable(field.Table.TableName))
                {
                    if (table.Supported && table.Columns != null)
                    {
                        foreach (var item in table.Columns)
                        {
                            if (item.Name == field.ColumnName)
                            {
                                item.Default = value;
                                return true;
                            }
                        }
                    }
                    return false;
                }
            }
            catch { return false; }
        }

        public virtual Boolean DropDefault(IDataColumn field)
        {
            return AddDefault(field, null);
        }
#endif
        #endregion

        #region 数据类型
        protected override DataRow[] FindDataType(IDataColumn field, string typeName, bool? isLong)
        {
            DataRow[] drs = base.FindDataType(field, typeName, isLong);
            if (drs != null && drs.Length > 0) return drs;

            //// 处理SByte类型
            //if (typeName == typeof(SByte).FullName)
            //{
            //    typeName = typeof(Byte).FullName;
            //    drs = base.FindDataType(field, typeName, isLong);
            //    if (drs != null && drs.Length > 0) return drs;
            //}

            DataTable dt = DataTypes;
            if (dt == null) return null;

            // 转为整数
            Int32 n = 0;
            if (!Int32.TryParse(typeName, out n)) return null;

            try
            {
                if (isLong == null)
                {
                    drs = dt.Select(String.Format("NativeDataType={0}", n));
                    if (drs == null || drs.Length < 1) drs = dt.Select(String.Format("ProviderDbType={0}", n));
                }
                else
                {
                    drs = dt.Select(String.Format("NativeDataType={0} And IsLong={1}", n, isLong.Value));
                    if (drs == null || drs.Length < 1) drs = dt.Select(String.Format("ProviderDbType={0} And IsLong={1}", n, isLong.Value));
                }
            }
            catch { }

            return drs;
        }

        protected override string GetFieldType(IDataColumn field)
        {
            String typeName = base.GetFieldType(field);

            //if (typeName.StartsWith("VarChar")) return typeName.Replace("VarChar", "Text");
            if (field.Identity) return null;

            return typeName;
        }
        #endregion

        #region 辅助函数
#if ACCESS
        ADOTabe GetTable(String tableName)
        {
            return new ADOTabe(Database.ConnectionString, FileName, tableName);
        }
#endif
        #endregion
    }

#if ACCESS
    #region ADOX封装
    internal class ADOTabe : /*DisposeBase*/IDisposable
    {
    #region ADOX属性
        private Table _Table;
        /// <summary>表</summary>
        public Table Table
        {
            get
            {
                if (_Table == null) _Table = Cat.Tables[TableName];
                return _Table;
            }
        }

        private String _ConnectionString;
        /// <summary>连接字符串</summary>
        public String ConnectionString
        {
            get { return _ConnectionString; }
            set { _ConnectionString = value; }
        }

        private String _FileName;
        /// <summary>文件名</summary>
        public String FileName
        {
            get { return _FileName; }
            set { _FileName = value; }
        }

        private ConnectionClass _Conn;
        /// <summary>链接</summary>
        public ConnectionClass Conn
        {
            get
            {
                if (_Conn == null)
                {
                    _Conn = new ConnectionClass();
                    _Conn.Open(ConnectionString, null, null, 0);
                }
                return _Conn;
            }
        }

        private Catalog _Cat;
        /// <summary></summary>
        public Catalog Cat
        {
            get
            {
                if (_Cat == null)
                {
                    _Cat = new CatalogClass();
                    _Cat.ActiveConnection = Conn;
                }
                return _Cat;
            }
        }
    #endregion

    #region DAO属性
        private String _TableName;
        /// <summary>表名</summary>
        public String TableName { get { return _TableName; } set { _TableName = value; } }

        private TableDef _TableDef;
        /// <summary>表定义</summary>
        public TableDef TableDef
        {
            get
            {
                if (_TableDef == null) _TableDef = Db.TableDefs[TableName];
                return _TableDef;
            }
        }

        private DBEngineClass _Dbe;
        /// <summary>链接</summary>
        public DBEngineClass Dbe
        {
            get
            {
                if (_Dbe == null) _Dbe = new DBEngineClass();
                return _Dbe;
            }
        }

        private DAO.Database _Db;
        /// <summary></summary>
        public DAO.Database Db
        {
            get
            {
                if (_Db == null) _Db = Dbe.OpenDatabase(FileName, null, null, null);
                return _Db;
            }
        }
    #endregion

    #region 扩展属性
        private List<ADOColumn> _Columns;
        /// <summary>字段集合</summary>
        public List<ADOColumn> Columns
        {
            get
            {
                if (_Columns == null)
                {
                    //Dictionary<String, DAO.Field> dic = new Dictionary<string, DAO.Field>();
                    //foreach (DAO.Field item in TableDef.Fields)
                    //{
                    //    dic.Add(item.Name, item);
                    //}

                    _Columns = new List<ADOColumn>();
                    foreach (Column item in Table.Columns)
                    {
                        //_Columns.Add(new ADOColumn(this, item, dic[item.Name]));
                        _Columns.Add(new ADOColumn(this, item));
                    }
                }
                return _Columns;
            }
        }

        /// <summary>是否支持</summary>
        public Boolean Supported
        {
            get
            {
                try
                {
                    return Conn != null;
                }
                catch
                {
                    return false;
                }
            }
        }

        /// <summary>描述</summary>
        public String Description
        {
            get
            {
                DAO.Property p = TableDef.Properties["Description"];
                if (p == null && p.Value == null)
                    return null;
                else
                    return p.Value.ToString();
            }
            set
            {
                DAO.Property p = null;
                try
                {
                    p = TableDef.Properties["Description"];
                }
                catch { }

                if (p != null)
                {
                    p.Value = value;
                }
                else
                {
                    try
                    {
                        p = TableDef.CreateProperty("Description", DAO.DataTypeEnum.dbText, value, false);
                        //Thread.Sleep(1000);
                        TableDef.Properties.Append(p);
                    }
                    catch (Exception ex)
                    {
                        XTrace.WriteLine("表" + Table.Name + "没有Description属性!" + ex.ToString());
#if DEBUG
                        throw new Exception("表" + Table.Name + "没有Description属性!", ex);
#endif
                    }
                }
            }
        }
    #endregion

    #region 构造
        public ADOTabe(String connstr, String filename, String tablename)
        {
            ConnectionString = connstr;
            FileName = filename;
            TableName = tablename;
        }

        public void Dispose()
        {
            try
            {
                if (_Columns != null && _Columns.Count > 0)
                {
                    foreach (var item in _Columns)
                    {
                        item.Dispose();
                    }
                }
                if (_Table != null) Marshal.ReleaseComObject(_Table);
                if (_Cat != null) Marshal.ReleaseComObject(_Cat);
                if (_Conn != null)
                {
                    _Conn.Close();
                    Marshal.ReleaseComObject(_Conn);
                }

                if (_TableDef != null) Marshal.ReleaseComObject(_TableDef);
                if (_Db != null)
                {
                    _Db.Close();
                    Marshal.ReleaseComObject(_Db);
                }
                if (_Dbe != null) Marshal.ReleaseComObject(_Dbe);
            }
            catch (Exception ex)
            {
                if (DAL.Debug) DAL.WriteLog(ex.ToString());
            }
        }
    #endregion
    }

    internal class ADOColumn : /*DisposeBase*/IDisposable
    {
    #region 属性
        private Column _Column;
        /// <summary>字段</summary>
        public Column Column
        {
            get { return _Column; }
            set { _Column = value; }
        }

        private ADOTabe _Table;
        /// <summary>表</summary>
        public ADOTabe Table
        {
            get { return _Table; }
            set { _Table = value; }
        }
    #endregion

    #region DAO属性
        //private DAO.Field _Field;
        ///// <summary>字段</summary>
        //public DAO.Field Field
        //{
        //    get { return _Field; }
        //    set { _Field = value; }
        //}
    #endregion

    #region 扩展属性
        /// <summary>名称</summary>
        public String Name
        {
            get { return Column.Name; }
            set { Column.Name = value; }
        }

        /// <summary>描述</summary>
        public String Description
        {
            get
            {
                ADOX.Property p = Column.Properties["Description"];
                if (p == null && p.Value == null)
                    return null;
                else
                    return p.Value.ToString();
            }
            set
            {
                ADOX.Property p = Column.Properties["Description"];
                if (p != null)
                    p.Value = value;
                else
                    throw new XCodeException("列" + Column.Name + "没有Description属性!");
            }
        }

        /// <summary>描述</summary>
        public String Default
        {
            get
            {
                ADOX.Property p = Column.Properties["Default"];
                if (p == null && p.Value == null)
                    return null;
                else
                    return p.Value.ToString();
            }
            set
            {
                ADOX.Property p = Column.Properties["Default"];
                if (p != null)
                    p.Value = value;
                else
                    throw new XCodeException("列" + Column.Name + "没有Default属性!");
            }
        }

        /// <summary>是否自增</summary>
        public Boolean AutoIncrement
        {
            get
            {
                ADOX.Property p = Column.Properties["Autoincrement"];
                if (p == null && p.Value == null)
                    return false;
                else
                    return (Boolean)p.Value;
            }
            set
            {
                ADOX.Property p = Column.Properties["Autoincrement"];
                if (p != null)
                    p.Value = value;
                else
                    throw new XCodeException("列" + Column.Name + "没有Autoincrement属性!");
            }
        }

        /// <summary>是否允许空</summary>
        public Boolean Nullable
        {
            get
            {
                ADOX.Property p = Column.Properties["Nullable"];
                if (p == null && p.Value == null)
                    return false;
                else
                    return (Boolean)p.Value;
            }
            set
            {
                ADOX.Property p = Column.Properties["Nullable"];
                if (p != null)
                    p.Value = value;
                else
                    throw new XCodeException("列" + Column.Name + "没有Nullable属性!");
            }
        }
    #endregion

    #region 构造
        public ADOColumn(ADOTabe table, Column column/*, DAO.Field field*/)
        {
            Table = table;
            Column = column;
            //Field = field;
        }

        public void Dispose()
        {
            try
            {
                if (Column != null) Marshal.ReleaseComObject(Column);
            }
            catch (Exception ex)
            {
                if (DAL.Debug) DAL.WriteLog(ex.ToString());
            }
        }
    #endregion
    }
    #endregion
#endif
}