最稳的pk10计划iphone 北京pk10计划手机软件 北京pk10数字的规律 超神手机版pk10软件 pk10北京赛车9码技巧 pk10四期倍投计划表 pk10极速赛车论坛 北京赛车冠军怎样选5码 北京赛车系统下载安装 pk10教程视频 北京pk10选号公式 北京赛车pk10赚钱技巧 北京赛车怎么提升概率 pk10技巧北京快三 北京pk10大小计划
VB.net 2010 視頻教程 VB.net 2010 視頻教程 VB.net 2010 視頻教程
SQL Server 2008 視頻教程 c#入門經典教程 Visual Basic從門到精通視頻教程
當前位置:
首頁 > 數據庫 > Access數據庫 >
  • access數據庫之讓ADO.NET Entity Framework 支持ACCESS數據

  • 2019-07-02 21:54 來源:未知

如寫的不好請見諒,本人水平有限。

個人簡歷及水平:。 http://www.cnblogs.com/hackdragon/p/3662599.html

接到一個程序和網頁交互的項目,用ADO.NET Entity Framework (以下簡稱EF)很快就搞完了,但是對方的空間提供的MSSQL數據庫比較昂貴,所以就采用ACCESS數據庫,但是我查了資料發現 EF不支持Access數據庫,(以前覺得LINQ TO SQL 不支持 這個應該支持),寫完的代碼不想用OLEDB在寫了,于是網上一頓查,試驗了ALINQ和其他很多的,總是不能符合項目的需要。不是更新不行就算插入失敗,要不就是經常查詢錯誤。最后沒辦法,我自己決定寫一個實體支持ACCESS數據庫,我覺得懶人應該有需要這個的,當然大俠們估計有更好的辦法來更懶一些。

懶人第一步:

因為VS的實體生成器不支持ACCESS數據庫,所以無法生成代碼,但是想快速開發項目,那么你可以用SQL數據庫先來設計,然后導出數據庫到ACCESS數據庫,這樣做的目的是讓生成器可以生成我們所需要的代碼。注意設計數據庫字段的時候要考慮他們的兼容性。

勤快第二步:

開始寫代碼了,原始的上下文代碼如下:

復制代碼
#region 上下文
    
    /// <summary>
    /// 沒有元數據文檔可用。
    /// </summary>
    public partial class SqlDoorEntities1 : ObjectContext
    {
        #region 構造函數
    
        /// <summary>
        /// 請使用應用程序配置文件的“SqlDoorEntities1”部分中的連接字符串初始化新 SqlDoorEntities1 對象。
        /// </summary>
        public SqlDoorEntities1() : base("name=SqlDoorEntities1", "SqlDoorEntities1")
        {
            OnContextCreated();
        }
    
        /// <summary>
        /// 初始化新的 SqlDoorEntities1 對象。
        /// </summary>
        public SqlDoorEntities1(string connectionString) : base(connectionString, "SqlDoorEntities1")
        {
            OnContextCreated();
        }
    
        /// <summary>
        /// 初始化新的 SqlDoorEntities1 對象。
        /// </summary>
        public SqlDoorEntities1(EntityConnection connection) : base(connection, "SqlDoorEntities1")
        {
            OnContextCreated();
        }
    
        #endregion
    
        #region 分部方法
    
        partial void OnContextCreated();
    
        #endregion
    
        #region ObjectSet 屬性
    
        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>
        public ObjectSet<CmdMsg> CmdMsg
        {
            get
            {
                if ((_CmdMsg == null))
                {
                    _CmdMsg = base.CreateObjectSet<CmdMsg>("CmdMsg");
                }
                return _CmdMsg;
            }
        }
        private ObjectSet<CmdMsg> _CmdMsg;
    
        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>
        public ObjectSet<Door> Door
        {
            get
            {
                if ((_Door == null))
                {
                    _Door = base.CreateObjectSet<Door>("Door");
                }
                return _Door;
            }
        }
        private ObjectSet<Door> _Door;
    
        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>
        public ObjectSet<Manager> Manager
        {
            get
            {
                if ((_Manager == null))
                {
                    _Manager = base.CreateObjectSet<Manager>("Manager");
                }
                return _Manager;
            }
        }
        private ObjectSet<Manager> _Manager;
    
        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>
        public ObjectSet<Users> Users
        {
            get
            {
                if ((_Users == null))
                {
                    _Users = base.CreateObjectSet<Users>("Users");
                }
                return _Users;
            }
        }
        private ObjectSet<Users> _Users;

        #endregion

        #region AddTo 方法
    
        /// <summary>
        /// 用于向 CmdMsg EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 ObjectSet&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToCmdMsg(CmdMsg cmdMsg)
        {
            base.AddObject("CmdMsg", cmdMsg);
        }
    
        /// <summary>
        /// 用于向 Door EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 ObjectSet&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToDoor(Door door)
        {
            base.AddObject("Door", door);
        }
    
        /// <summary>
        /// 用于向 Manager EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 ObjectSet&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToManager(Manager manager)
        {
            base.AddObject("Manager", manager);
        }
    
        /// <summary>
        /// 用于向 Users EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 ObjectSet&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToUsers(Users users)
        {
            base.AddObject("Users", users);
        }

        #endregion

    }

    #endregion
復制代碼

ObjectContext 繼承于IDisposable 那么我寫一個自己的 ObjectContext 這樣的類 我給他起個名字叫EFToAccess 那么多 構造方法 我們就需要2個一個 是 給定的連接字符串 一個是默認從webconfig中讀取的鏈接字符串就可以了。本人偷懶,直接讀取指定的路徑了。數據庫的簡單讀寫可能都依賴一個where查詢,那么怎么實現自己的where查詢就很關鍵,于是我看資料研究了2天Lambda Expression 表達式。最后還是看了 博客園的一篇 擴展LINQ to SQL:使用Lambda Expression批量刪除數據才會用,現在也不是很明白,懶人就是拿來主義,不怎么消化,我現在也沒多少時間消化知識,估計這樣的人也不少吧。下面是我自己用的的方法,利用VS生成的代碼 2個替換1個刪除搞定 (ObjectContext替換“你自己的類名我的是SqlDoorEntities”,ObjectSet替換成IEnumerable,刪除無用的構造函數)

復制代碼
public class SqlDoorEntities : EFToAccess
    {
        public SqlDoorEntities():base("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" 
+AppDomain.CurrentDomain.BaseDirectory + "bin\\DataDoor.mdb")

        {
        }
        #region IEnumerable 屬性
        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>

        public IEnumerable<CmdMsg> CmdMsg
        {
            get
            {
                if ((_CmdMsg == null))
                {
                    _CmdMsg = base.CreateObjectSet<CmdMsg>("CmdMsg");
                }
                return _CmdMsg;
            }
        }
        private IEnumerable<CmdMsg> _CmdMsg;

        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>
        public IEnumerable<Door> Door
        {
            get
            {
                if ((_Door == null))
                {
                    _Door = base.CreateObjectSet<Door>("Door");
                }
                return _Door;
            }
        }
        private IEnumerable<Door> _Door;

        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>
        public IEnumerable<Manager> Manager
        {
            get
            {
                if ((_Manager == null))
                {
                    _Manager = base.CreateObjectSet<Manager>("Manager");
                }
                return _Manager;
            }
        }
        private IEnumerable<Manager> _Manager;

        /// <summary>
        /// 沒有元數據文檔可用。
        /// </summary>
        public IEnumerable<Users> Users
        {
            get
            {
                if ((_Users == null))
                {
                    _Users = base.CreateObjectSet<Users>("Users");
                }
                return _Users;
            }
        }
        private IEnumerable<Users> _Users;

        #endregion
        #region AddTo 方法

        /// <summary>
        /// 用于向 CmdMsg EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 IEnumerable&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToCmdMsg(CmdMsg cmdMsg)
        {
            base.AddObject("CmdMsg", cmdMsg);
        }

        /// <summary>
        /// 用于向 Door EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 IEnumerable&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToDoor(Door door)
        {
            base.AddObject("Door", door);
        }

        /// <summary>
        /// 用于向 Manager EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 IEnumerable&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToManager(Manager manager)
        {
            base.AddObject("Manager", manager);
        }

        /// <summary>
        /// 用于向 Users EntitySet 添加新對象的方法,已棄用。請考慮改用關聯的 IEnumerable&lt;T&gt; 屬性的 .Add 方法。
        /// </summary>
        public void AddToUsers(Users users)
        {
            base.AddObject("Users", users);
        }

        #endregion
    }
復制代碼

懶人第三步:

為了讓代碼和EF使用方法基本一致,所以不得不做一些工作讓我寫的類基本滿足項目需要。首先實現一個讓Lambda Expression 表達式變成字符串的函數

復制代碼
string GetWhereString(Expression Func)
        {
            ConditionBuilder conditionBuilder = new ConditionBuilder();
            conditionBuilder.Build(Func);
            for (int i = 0; i < conditionBuilder.Arguments.Length; i++)
            {
                object ce = conditionBuilder.Arguments[i];
                if (ce == null)
                    conditionBuilder.Arguments[i] = "null";
                else if (ce is ValueType)
                    conditionBuilder.Arguments[i] = ce.ToString();
                else if (ce is string || ce is char)
                    conditionBuilder.Arguments[i] = string.Format("'{0}'", ce.ToString());
                else if (ce is DateTime)
                    conditionBuilder.Arguments[i] = string.Format("#{0}#", ce.ToString());

            }
            return string.Format(conditionBuilder.Condition, conditionBuilder.Arguments);
        }
復制代碼

上面的ConditionBuilder類代碼我就不貼出了。大家參考我提到的那篇文章,如果實際應用當中,有死循環的地方那么應該在該調用基類的地方加入base.XXX比如base.Visit

實現我們自己的where 這里如果我們自己生成類 那么我們的實體類類可以直接有一個where 方法,但是我為了能讓我們懶人使用VS生成的實體類只能這么實現了。為了代碼利用率,我們還需要另外2個函數。

取得所有記錄

復制代碼
IEnumerable<TEntity> SelectAll<TEntity>() where TEntity : new()
        {
            TEntity TDefault = new TEntity();
            string entitySetName = TDefault.GetType().Name;
            string strSqlQuery = string.Format("SELECT * FROM {0}", entitySetName);
            m_LastSqlCommand = strSqlQuery;
            return SelectWhere<TEntity>(strSqlQuery);
        }
復制代碼

經常的條件查詢

復制代碼
public IEnumerable<TEntity> Where<TEntity>(Expression<Func<TEntity, bool>> Func) where TEntity : new()
        {
            TEntity TDefault = new TEntity();
            string entitySetName = TDefault.GetType().Name;
            string strWhere = GetWhereString(Func).Replace("Where", entitySetName);
            string strSqlQuery = string.Format("SELECT * FROM {0} WHERE {1} ", entitySetName, strWhere);
            m_LastSqlCommand = strSqlQuery;
            return SelectWhere<TEntity>(strSqlQuery);
        }
復制代碼

最后的where

復制代碼
IEnumerable<TEntity> SelectWhere<TEntity>(string strSqlQuery) where TEntity : new()
        {
            TEntity TDefault = new TEntity();
            //確認基礎類型是否是 EntityObject類型
            Type TBase = TDefault.GetType();
            while ((TBase.BaseType) != null)
            {
                if (TBase.Name == "EntityObject") break;
                TBase = TBase.BaseType;
            }
            bool IsPCEH = false;
            if (TBase != null && TBase.Name == "EntityObject")  IsPCEH = true;
            PropertyInfo[] properties = TDefault.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            List<TEntity> Records = new List<TEntity>();
            string entitySetName = TDefault.GetType().Name;
            try
            {
                OleDbCommand Cmd = new OleDbCommand(strSqlQuery, AccessConn);
                OleDbDataReader sqlReader = Cmd.ExecuteReader();
                #region 數據庫查詢開始
                while (sqlReader.Read())
                {
                    TEntity TValue = new TEntity();
                    //輸入是EntityObject類型,那么加入屬性改變事件
                    if (IsPCEH)
                    {
                        EntityObject EO = TValue as EntityObject;
                        EO.PropertyChanged += PropertyChangedEH;
                    }
                    for (int i = 0; i < sqlReader.FieldCount; i++)
                    {
                        string strField = sqlReader.GetName(i);
                        //根據字段名 反射 類的屬性
                        PropertyInfo p = properties.Where(P => string.Compare(P.Name, strField, true) == 0).First();
                        #region 數據轉換
                        switch (p.PropertyType.Name.ToString().ToLower())
                        {
                            case "int16":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetInt16(i), null);
                                break;
                            case "int32":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetInt32(i), null);
                                break;
                            case "int64":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetInt64(i), null);
                                break;
                            case "string":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetString(i), null);
                                break;
                            case "double":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetDouble(i), null);
                                break;
                            case "float":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetFloat(i), null);
                                break;
                            case "decimal":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetDecimal(i), null);
                                break;
                            case "datetime":
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetDateTime(i), null);
                                break;
                            default:
                                if (!sqlReader.IsDBNull(i)) p.SetValue(TValue, sqlReader.GetValue(i), null);
                                break;
                        }
                        #endregion

                    }
                    Records.Add(TValue);
                }
                #endregion
                Cmd.Clone();
                m_IsDetectionChange = true;
            }
            catch (Exception)
            {
                throw;
            }
            return Records;
        }
復制代碼

屬性的改變(也就是數據庫記錄的字段值)我們要知道才能實現EF的SaveChanges()函數那么我們需要簡歷一個數組變量,直接上代碼

//表名            //主鍵              //屬性    值1 值2 主鍵類型名字
        Dictionary<string, Dictionary<string, Dictionary<string, object[]>>> m_ArrDetection = new Dictionary<string, Dictionary<string, Dictionary<string, object[]>>>();
復制代碼
void PropertyChangedEH(object sender, PropertyChangedEventArgs e)
        {
            //沒有開啟返回
            if (!m_IsDetectionChange) return;
            //反射所有屬性
            PropertyInfo[] properties = sender.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            //查詢主鍵
            PropertyInfo EntityKey = GetEntityKeyFormAllProperty(properties);
            //沒有主鍵的返回(表必須要有主鍵)
            if (EntityKey == null) return;
            //表名字
            string Table = sender.GetType().Name;
            //主鍵值
            string MainKey = EntityKey.GetValue(sender, null).ToString();
            if (MainKey == null || MainKey == "") return;
            //沒有表 就添加
            if (!m_ArrDetection.ContainsKey(Table)) m_ArrDetection[Table] = new Dictionary<string, Dictionary<string, object[]>>();
            //沒有主鍵 就添加
            if (!m_ArrDetection[Table].ContainsKey(MainKey)) m_ArrDetection[Table][MainKey] = new Dictionary<string, object[]>();
            //主鍵是不用更新的(一般數據庫主鍵都是自動增長的吧,尤其快速開發的項目)
            if (e.PropertyName == MainKey) return;
            PropertyInfo p = properties.Where(P => string.Compare(P.Name, e.PropertyName, true) == 0).First();
            //賦值
            m_ArrDetection[Table][MainKey][e.PropertyName] = new object[2] { p.GetValue(sender, null), EntityKey.Name };
        }
復制代碼

查找主鍵的函數

復制代碼
private bool IsEntityKeyProperty(PropertyInfo Info)
        {
            foreach (Attribute attr in Attribute.GetCustomAttributes(Info))
            {
                if (attr is System.Data.Objects.DataClasses.EdmScalarPropertyAttribute)
                {
                    System.Data.Objects.DataClasses.EdmScalarPropertyAttribute Key = (System.Data.Objects.DataClasses.EdmScalarPropertyAttribute)attr;
                    if (Key.EntityKeyProperty == true)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        private PropertyInfo GetEntityKeyFormAllProperty(PropertyInfo[] properties)
        {
            foreach (PropertyInfo Info in properties)
            {
                if (IsEntityKeyProperty(Info)) return Info;
            }
            return null;
        }
      



  
pk10赛车冠军技巧
最稳的pk10计划iphone 北京pk10计划手机软件 北京pk10数字的规律 超神手机版pk10软件 pk10北京赛车9码技巧 pk10四期倍投计划表 pk10极速赛车论坛 北京赛车冠军怎样选5码 北京赛车系统下载安装 pk10教程视频 北京pk10选号公式 北京赛车pk10赚钱技巧 北京赛车怎么提升概率 pk10技巧北京快三 北京pk10大小计划
体彩重庆百变王牌规则 排列三走势图专业版 高佣联盟app能赚钱是真的 百搭麻将游戏下载 奔驰宝马游戏机破解器 开个150平米超市赚钱吗 安徽十一选五专家推荐 139彩票网苹果 内蒙古11选5走势图任选