zoukankan      html  css  js  c++  java
  • 让ADO.NET Entity Framework 支持ACCESS数据库

    如写的不好请见谅,本人水平有限。

    个人简历及水平:。 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;
            }

    在实际的调用过程中,我们使用基本可以和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。下面是用到的源文件。

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

  • 相关阅读:
    Asm Instance Parameter Best Practice
    Real Application Testing Database Replay、SPA的价格和介绍
    11g OCM Upgrade Exam Tips
    如何在文本框输入框里按回车键,光标自动跳转到下一个文本框输入框或者是执行某按钮的提交?
    asp.net textbox回车变成按扭事件
    图片判断你的左脑发达还是右脑发达 (转)
    关于Oracle数据和对象的导入导出 [转]
    ajax web.config配置与发布
    批处理复制最新的文件夹里面的bmp文件到指定目录
    C#调用存储过程返回值
  • 原文地址:https://www.cnblogs.com/hackdragon/p/3677120.html
Copyright © 2011-2022 走看看