-
access数据库之让ADO.NET Entity Framework 支持ACCESS数据(2)
在实际的调用过程中,我们使用基本可以和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