讓ADO.NET Entity Framework 支持ACCESS數據庫

如寫的很差請見諒,本人水平有限。

我的簡歷及水平:。 http://www.cnblogs.com/hackdragon/p/3662599.htmlhtml

接到一個程序和網頁交互的項目,用ADO.NET Entity Framework (如下簡稱EF)很快就搞完了,可是對方的空間提供的MSSQL數據庫比較昂貴,因此就採用ACCESS數據庫,可是我查了資料發現 EF不支持Access數據庫,(之前以爲LINQ TO SQL 不支持 這個應該支持),寫完的代碼不想用OLEDB在寫了,因而網上一頓查,試驗了ALINQ和其餘不少的,老是不能符合項目的須要。不是更新不行就算插入失敗,要不就是常常查詢錯誤。最後沒辦法,我本身決定寫一個實體支持ACCESS數據庫,我以爲懶人應該有須要這個的,固然大俠們估計有更好的辦法來更懶一些。web

懶人第一步:

由於VS的實體生成器不支持ACCESS數據庫,因此沒法生成代碼,可是想快速開發項目,那麼你能夠用SQL數據庫先來設計,而後導出數據庫到ACCESS數據庫,這樣作的目的是讓生成器能夠生成咱們所須要的代碼。注意設計數據庫字段的時候要考慮他們的兼容性。sql

勤快第二步:

開始寫代碼了,原始的上下文代碼以下:數據庫

#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 表達式變成字符串的函數ide

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個函數。ui

取得全部記錄spa

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;
        }

在實際的調用過程當中,咱們使用基本能夠和EF使用同樣

public ActionResult Index()
        {
            int UID = GetUerID();
            List<Door> Arr = new List<Door>();
            try
            {
                // TODO: Add insert logic here
                using (SqlDoorEntities Database = new SqlDoorEntities())
                {
                    //EF寫法 
                    //IEnumerable<Door> Records = Database.Door.Where(R => R.U_ID == UID);
                    IEnumerable<Door> Records = Database.Where<Door>(R => R.U_ID == UID);
                    foreach (Door Record in Records) Arr.Add(Record);
                }

            }
            catch (Exception E)
            {
                return Content(E.Message);
            }
            return View(Arr);
        }

固然你能夠直接用EF的方式 ,缺點就是直接把整個表的數據都讀取過來了。下面我依次說說 數據庫的 增長 刪除 修改;

增長

實現CreateObjectSet,懶人嘛,要不還得去修改。

public IEnumerable<TEntity> CreateObjectSet<TEntity>(string entitySetName) where TEntity : new()
        {
            return  SelectAll<TEntity>();
        }

 

實現AddObject 直接一個簡單把對象插入到數組中。實現的時候可讓SaveChanges()在處理

List<object> m_ArrAdd = new List<object>();
public void AddObject(string strName, object o)
        {
            m_ArrAdd.Add(o);
        }

總說SaveChanges()那麼先把他貼出來

public int SaveChanges()
        {
            if (m_ArrDel.Count > 0)
            {
                DeleteAll();
                m_ArrDel.Clear();
            }
            if (m_ArrAdd.Count > 0)
            {
                AddAll();
                m_ArrAdd.Clear();
            }
            if (m_ArrDetection.Count > 0)
            {
                AutoUpdate();
                m_ArrDetection.Clear();
            }
            m_IsDetectionChange = false;
            return 0;
        }

其實也沒什麼,就是看看數組中哪一個有了須要增刪改的 就處理下,接着寫添加全部的函數。

int AddAll()
        {
            foreach (object O in m_ArrAdd)
            {
                AddNew(O);
            }
            return 0;
        }

下面該實現咱們的insert into 了 直接使用也是能夠的 就不用使用糾結的SaveChanges()了。

public int AddNew<TEntity>(TEntity TDefault) where TEntity : class
        {
            PropertyInfo[] properties = TDefault.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo EntityKey = GetEntityKeyFormAllProperty(properties);
            if (EntityKey == null) throw new Exception("未設置主鍵,沒法使用本函數請使用其餘函數!");
            string TabName = TDefault.GetType().Name;
            string EntityValue = "";
            string strRows = "";
            string strValues = "";
            #region Rows Values
            foreach (PropertyInfo Info in properties)
            {
                object ce = Info.GetValue(TDefault, null);
                string strLeft = Info.Name;
                string strRight = "";
                if (ce == null)
                    continue;
                else if (ce is DateTime)
                    strRight = string.Format("#{0}#", ce.ToString());
                else if (ce is ValueType)
                    strRight = ce.ToString();
                else if (ce is ValueType)
                    strRight = ce.ToString();
                else if (ce is string || ce is char)
                    strRight = string.Format("'{0}'", ce.ToString());
                if (strLeft == EntityKey.Name)
                {
                    EntityValue = strRight;
                    continue;
                }
                if (strRight.Length == 0) continue;
                if (strLeft == "EntityKey" || strLeft == "EntityState") continue;
                strRows = strRows + strLeft + ",";
                strValues = strValues + strRight + ",";
            }
            #endregion
            if (strRows.Length < 2 || strValues.Length < 2) throw new Exception("SQL語句錯誤");
            strRows = strRows.Remove(strRows.Length - 1);
            strValues = strValues.Remove(strValues.Length - 1);
            string strSqlQuery = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", TabName, strRows, strValues);
            m_LastSqlCommand = strSqlQuery;
            try
            {
                OleDbCommand Cmd = new OleDbCommand(strSqlQuery, AccessConn);
                Cmd.ExecuteNonQuery();
            }
            catch (Exception)
            {
                throw;
            }
            return 0;
        }

函數中也沒什麼,就是注意一下不要生成SQL語句的時候,把主鍵信息也生成進去,通常狀況主鍵大可能是個自動增加的數字吧。還有就是不要把EntityObject的屬性的特有主鍵信息寫入到數據庫中。根據反射寫入數據庫。

刪除

仍是先現實EF的刪除方法DeleteObject

public void DeleteObject(object TDefault)
        {
            PropertyInfo[] properties = TDefault.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo EntityKey = GetEntityKeyFormAllProperty(properties);
            if (EntityKey == null) throw new Exception("未設置主鍵,沒法使用本函數請使用其餘函數!");
            string EntityValue = EntityKey.GetValue(TDefault, null).ToString();
            if (EntityValue == null || EntityValue == "") throw new Exception("反射取值失敗!");
            string entitySetName = TDefault.GetType().Name;
            string KeyName = TDefault.GetType().Name;
            if (!m_ArrDel.ContainsKey(KeyName)) m_ArrDel.Add(KeyName,new List<string>());
            m_ArrDel[KeyName].Add(string.Format("(({0})={1})", EntityKey.Name, EntityValue));
        }

而後咱們須要創建咱們本身的列表

Dictionary<string, List<string>> m_ArrDel = new Dictionary<string, List<string>>();

 

實現刪除函數

public int Delete<TEntity>(TEntity TDefault)
        {
            PropertyInfo[] properties = TDefault.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo EntityKey = GetEntityKeyFormAllProperty(properties);
            if (EntityKey == null) throw new Exception("未設置主鍵,沒法使用本函數請使用其餘函數!");
            string EntityValue = EntityKey.GetValue(TDefault, null).ToString();
            if (EntityValue == null || EntityValue == "") throw new Exception("反射取值失敗!");
            string entitySetName = TDefault.GetType().Name;
            string strSqlQuery = string.Format("DELETE FROM {0} WHERE {1}={2} ", entitySetName, EntityKey, EntityValue);
            m_LastSqlCommand = strSqlQuery;
            try
            {
                OleDbCommand Cmd = new OleDbCommand(strSqlQuery, AccessConn);
                Cmd.ExecuteNonQuery();
            }
            catch (Exception)
            {
                throw;
            }
            return 0;
        }

更新

這裏是根據主鍵更新的,沒有實現update …where…,由於每每都是查詢到記錄,而後根據這個記錄更新的,因此還須要更多代碼的實現Select等,爲了這個小的項目進度沒有寫完。上面代碼已經告訴了,能夠偵測到查詢到的屬性的變動因此SaveChanges()保存更改時,咱們就直接根據數組進行更改了。

public int AutoUpdate()
        {
            List<string> ArrSqlText = new List<string>();
            foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, object[]>>> TabKVP in m_ArrDetection)
            {
                //遍歷表名
                string TabName = TabKVP.Key;
                foreach (KeyValuePair<string, Dictionary<string, object[]>> KeyKVP in TabKVP.Value)
                {
                    string strSet = "";
                    string strMainKeyName = "";
                    #region 把數據列出來例如: a=1,c="2"
                    foreach (KeyValuePair<string, object[]> ValueKVP in KeyKVP.Value)
                    {
                        if (strMainKeyName.Length == 0) strMainKeyName = ValueKVP.Value[1].ToString();
                        object Va = ValueKVP.Value[0];
                        string strLeft = ValueKVP.Key;
                        string strRight = "";
                        #region 根據值確認是否添加引號
                        if (ValueKVP.Value == null)
                            continue;
                        else if (Va is DateTime)
                            strRight = string.Format("#{0}#", Va.ToString());
                        else if (Va is ValueType)
                            strRight = Va.ToString();
                        else if (Va is string || Va is char)
                            strRight = string.Format("'{0}'", Va.ToString());
                        #endregion
                        if (strRight.Length == 0) continue;
                        if (strLeft == "EntityKey" || strLeft == "EntityState") continue;
                        strSet += strLeft + "=" + strRight + ",";

                    }
                    #endregion
                    if (strSet.Length < 2) continue;
                    strSet = strSet.Remove(strSet.Length - 1);
                    //根據當前的主鍵[ID] 生成一個SQL語句
                    string strSqlQuery = string.Format("UPDATE {0} SET {1} WHERE {2}={3} ", TabName, strSet, strMainKeyName, KeyKVP.Key);
                    ArrSqlText.Add(strSqlQuery);
                }
            }
            foreach (string strSqlQuery in ArrSqlText)
            {
                m_LastSqlCommand = strSqlQuery;
                try
                {
                    OleDbCommand Cmd = new OleDbCommand(strSqlQuery, AccessConn);
                    Cmd.ExecuteNonQuery();
                }
                catch
                {
                }

            }
            return 0;
        }

固然咱們還有直接把對象直接賦值拷貝的時候( a = b),這時候是偵測不到屬性的變化的,因此咱們要另一個函數來支持更新,就是讓他實現偵測到屬性的變化。

public void CopyPropertiesFrom(object destObject, object sourceObject)
        {
            if (destObject.GetType().Name != destObject.GetType().Name) throw new Exception("類型不一樣");
            PropertyInfo[] destProperties = destObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo[] sourceProperties = sourceObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo EntityKey = GetEntityKeyFormAllProperty(destProperties);
            if (EntityKey == null) throw new Exception("未設置主鍵,沒法使用本函數請使用其餘函數!");
            
            for (int i = 0; i < destProperties.Length; i++)
            {
                if (destProperties[i]==null|| destProperties[i].Name == EntityKey.Name) continue;
                if (destProperties[i].Name == "EntityKey" || destProperties[i].Name == "EntityState") continue;
                object DstV = destProperties[i].GetValue(destObject,null);
                object SrcV = sourceProperties[i].GetValue(sourceObject, null);
                if (SrcV == null) continue;//源 是NULL 不拷貝
                if (DstV.ToString() == SrcV.ToString()) continue;
                destProperties[i].SetValue(destObject, SrcV,null);
                //Action<object, object> LmdSetProp = LmdSet(destObject.GetType(), destProperties[i].Name);
                //LmdSetProp(destObject, SrcV);
            }

        }

顯示-添加-刪除-修改的例子代碼

#region 顯示用戶
        [Authorize(Roles = "manager")]
        public ActionResult Index()
        {
            List<Users> Users = new List<Users>();
            Users u = new Users();
            try
            {
                using (SqlDoorEntities Database = new SqlDoorEntities())
                {
                    IEnumerable<Users> Records = Database.Users;
                    if (Records.Count() > 0)
                    {
                        foreach (Users U in Records) Users.Add(U);
                    }
                }
            }
            catch { }
            return View(Users);
        }
        #endregion

        #region 建立用戶
        [Authorize(Roles = "manager")]
        [HttpPost]
        public ActionResult CreateUser(Users collection)
        {
            try
            {
                // TODO: Add insert logic here
                using (SqlDoorEntities Database = new SqlDoorEntities())
                {
                    IEnumerable<Users> Records = Database.Where<Users>(R => R.U_Number == collection.U_Number);
                    if (Records.Count() > 0)
                    {
                        ModelState.AddModelError("", "已經有了記錄了!");
                        return RedirectToAction("Index");
                    }
                    Database.AddToUsers(collection);
                    Database.SaveChanges();
                    //collection.U_LastIP = GetWebClientIp();
                }
                return RedirectToAction("Index");
            }
            catch (Exception E)
            {
                ModelState.AddModelError("", "數據庫錯誤!" + E.Message);
            }
            return View();
        }
        [Authorize(Roles = "manager")]
        public ActionResult CreateUser()
        {
            return View();
        }
        #endregion

        #region 編輯用戶
        [Authorize(Roles = "manager")]
        [HttpPost]
        public ActionResult EditUser(int id, Users collection)
        {
            try
            {
                // TODO: Add insert logic here
                
                using (SqlDoorEntities Database = new SqlDoorEntities())
                {
                    Users Record = Database.Where<Users>(R => R.U_ID == id).FirstOrDefault();
                    //Database.Update<Users>(Record);
                    Database.CopyPropertiesFrom(Record, collection);
                    Database.SaveChanges();
                }
                return Content("OK");
            }
            catch (Exception E)
            {
                return Content(E.Message);
            }
        }
        #endregion

        #region 刪除用戶
        [Authorize(Roles = "manager")]
        public ActionResult DeleteUser(int id)
        {
            try
            {
                // TODO: Add insert logic here

                using (SqlDoorEntities Database = new SqlDoorEntities())
                {
                    Users Record = Database.Where<Users>(R => R.U_ID == id).FirstOrDefault();
                    if (User != null)
                    {
                        Database.DeleteObject(Record);
                        Database.SaveChanges();
                    }
                }
            }
            catch
            {

            }
            return RedirectToAction("Index");
        }
        #endregion

最後

算是寫完了,也算是我cnblog的第一篇技術類文章吧。寫的不對的地方歡迎指正啊。本人QQ78486367。下面是用到的源文件。

http://files.cnblogs.com/hackdragon/EFToAccess.zip

相關文章
相關標籤/搜索