• EF6+MYSQL之初体验


    初次使用EF6+MYSQL

    这次的项目时间可拉得够长的,定制开发就是这样。客户真正用上了才能基本上不再改了。起先项目是php实现的,改造成桌面程序。用.net winform开发,像这种小项目肯定要用EF了。 以前一直用4.0,用DB First,把向导生成的模型扩展一下,另写一个分部类来实现bulkcopy等这种特殊需求。一直都是这样简单的用着,懒得花时间成本去搞高深的AOP/IOC/泛型工厂... 有时候就是越简单越好,当只会捉老鼠的猫就好。 这次依然还是使用的DB First。

    经验总结:

    1、EF6之CRUD

    EF向导自动转换成的DbContext类:

    public partial class POS_Entities : DbContext
        {
            public POS_Entities()
                : base("name=POS_Entities")
            {
            }
        
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                throw new UnintentionalCodeFirstException();
            }
        
            public virtual DbSet<bm_brandclasses> bm_brandclasses { get; set; }
            public virtual DbSet<bm_brandsubclasses> bm_brandsubclasses { get; set; }
            public virtual DbSet<bm_membermng> bm_membermng { get; set; }
            public virtual DbSet<bm_memcard_privilege> bm_memcard_privilege { get; set; }
            public virtual DbSet<bm_memcardclasses> bm_memcardclasses { get; set; }
            public virtual DbSet<bm_pointmng> bm_pointmng { get; set; }
            public virtual DbSet<ls_busimng> ls_busimng { get; set; }
            public virtual DbSet<ls_cashierlist> ls_cashierlist { get; set; }
            public virtual DbSet<ls_cashierlist_detail> ls_cashierlist_detail { get; set; }
            public virtual DbSet<ls_cashiernum> ls_cashiernum { get; set; }
            public virtual DbSet<ls_commoditymng> ls_commoditymng { get; set; }
            public virtual DbSet<ls_couponmng> ls_couponmng { get; set; }
            public virtual DbSet<ls_couponmng_list> ls_couponmng_list { get; set; }
            public virtual DbSet<ls_handovermng> ls_handovermng { get; set; }
            public virtual DbSet<ls_promotionclasses> ls_promotionclasses { get; set; }
            public virtual DbSet<ls_promotionmng> ls_promotionmng { get; set; }
            public virtual DbSet<ls_promotionmng_subact> ls_promotionmng_subact { get; set; }
            public virtual DbSet<ls_promotionsubclasses> ls_promotionsubclasses { get; set; }
            public virtual DbSet<sa_manager> sa_manager { get; set; }
            public virtual DbSet<sa_num_auto> sa_num_auto { get; set; }
            public virtual DbSet<sa_role> sa_role { get; set; }
            public virtual DbSet<ls_leasemng> ls_leasemng { get; set; }
        }
    

    我的扩展类:

    public partial class POS_Entities
        {
            private static readonly BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic;
    
            private static readonly Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            public string ConnectionString
            {
                get
                {
                    var ecb = new EntityConnectionStringBuilder(config.ConnectionStrings.ConnectionStrings["POS_Entities"].ConnectionString);
                    return ecb.ProviderConnectionString;
                }
            }
            /// <summary>
            /// 执行Sql语句
            /// </summary>
            /// <param name="sql"></param>
            /// <returns></returns>
            public int ExecuteSql(string sql)
            {
                return this.Database.ExecuteSqlCommand(sql, new object[] { });
            }
    
            /// <summary>
            /// 返回查询的第一行第一列的值
            /// </summary>
            /// <param name="sqlText"></param>
            /// <returns></returns>
            public object ExecuteScalar(string sqlText)
            {
                var db = this.Database.Connection;
                try
                {
                    if (db.State != ConnectionState.Open)
                        db.Open();
                    var cmd = db.CreateCommand();
                    cmd.CommandText = sqlText;
                    return cmd.ExecuteScalar();
                }
                finally
                {
                    db.Close();
                }
            }
    
            /// <summary>
            /// 使用同一个事物批量提交SQL
            /// </summary>
            /// <param name="sqls"></param>
            public bool BatchExecuteSqlWithTrans(List<string> sqls)
            {
                var dbConn = this.Database.Connection;
                if (dbConn.State != ConnectionState.Open)
                    dbConn.Open();
                var cmd = dbConn.CreateCommand();
                var st = dbConn.BeginTransaction();
                try
                {
                    HashSet<string> list = new HashSet<string>();
                    cmd.Transaction = st;
                    sqls.ForEach(delegate (string sqlTxt)
                    {
                        cmd.CommandText = sqlTxt;
                        cmd.ExecuteNonQuery();
                    });
                    st.Commit();
                    return true;
                }
                catch (Exception ex)
                {
                    st.Rollback();
                    return false;
                    throw new Exception(ex.Message);
                }
                finally
                {
                    dbConn.Close();
                }
            }
    
            #region MySql 批量插入
            /// <summary>
            /// 批量插入
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="tbName">要插入的目标表名称</param>
            /// <param name="columeArr">要插入的列名数组</param>
            /// <param name="listModels">要插入的实体数组</param>
            /// <param name="strConnection">数据库连接字符串</param>
            /// <returns></returns>
            public int BatchInsert<T>(string tbName, string[] columeArr, IList<T> listModels) where T : class, new()
            {
                if (listModels == null || listModels.Count == 0)
                {
                    throw new ArgumentException("没有需要批量插入的数据");
                }
                int columes = columeArr.Length;
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("INSERT INTO {0} ", tbName);
                AppendColumes(sb, columeArr);
                sb.Append(" VALUES ");
                var listParamKeys = new List<string>();//参数的键值
                string paramKey = string.Empty;
                for (int i = 0; i < listModels.Count; i++)  //构造参数
                {
                    sb.Append("(");
                    for (int j = 0; j < columes; j++)
                    {
                        paramKey = string.Format("@v_{0}_{1}", columeArr[j], columes * i + j); //参数前必须加入@
                        sb.Append(paramKey);
                        listParamKeys.Add(paramKey);
                        if (j < columes - 1)
                        {
                            sb.Append(",");
                        }
                    }
                    sb.Append("),");
                }
                var listParamValues = new List<object>();
                for (int i = 0; i < listModels.Count; i++)  //构造参数值数组
                {
                    FastPrepareParamValue<T>(listModels[i], columeArr, listParamValues);
                }
                string sqlText = sb.ToString().Trim(',') + ";";
                int affectNum = ExecuteNonQuery(ConnectionString, CommandType.Text, sqlText, PrepareParameters(listParamKeys.ToArray(), listParamValues.ToArray()));
                return affectNum;
            }
            private int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters)
            {
                MySqlCommand cmd = new MySqlCommand();
                using (MySqlConnection conn = new MySqlConnection(connectionString))
                {
                    PrepareCommand(conn, null, cmd, cmdType, cmdText, commandParameters);
                    int val = cmd.ExecuteNonQuery();
                    cmd.Parameters.Clear();
                    return val;
                }
            }
            private MySqlParameter[] PrepareParameters(string[] paramKeys, object[] paramValues)
            {
                MySqlParameter[] clonedParms = new MySqlParameter[paramKeys.Length];
                for (int i = 0; i < paramKeys.Length; i++)
                {
                    clonedParms[i] = new MySqlParameter(paramKeys[i], paramValues[i]);
                }
                return clonedParms;
            }
            private void PrepareCommand(MySqlConnection conn, MySqlTransaction trans, MySqlCommand cmd, CommandType cmdType, string cmdText, MySqlParameter[] cmdParms)
            {
                if (conn.State != ConnectionState.Open)
                    conn.Open();
                cmd.Connection = conn;
                cmd.CommandText = cmdText;
                if (trans != null)
                    cmd.Transaction = trans;
                cmd.CommandType = cmdType;
                if (cmdParms != null)
                {
                    foreach (MySqlParameter parm in cmdParms)
                        cmd.Parameters.Add(parm);
                }
            }
    
            private void AppendColumes(StringBuilder sb, string[] columeArr)
            {
                if (columeArr == null || columeArr.Length == 0)
                {
                    throw new ArgumentException("插入列不能为空");
                }
                sb.Append("(");
                for (int i = 0; i < columeArr.Length; i++)
                {
                    sb.Append(columeArr[i]);
                    if (i < columeArr.Length - 1)
                    {
                        sb.Append(",");
                    }
                }
                sb.Append(")");
            }
    
            private void FastPrepareParamValue<T>(T model, string[] columeArr, List<object> listPramValues)
            {
                object objValue = null;
                var objType = model.GetType();
                var properties = objType.GetProperties(bf);
                foreach (var columeName in columeArr)
                {
                    foreach (var propInfo in properties)
                    {
                        if (string.Compare(columeName, propInfo.Name, true) != 0)
                        {
                            continue;
                        }
                        try
                        {
                            objValue = propInfo.GetValue(model);
                        }
                        catch
                        {
                            objValue = null;
                        }
                        finally
                        {
                            listPramValues.Add(objValue);
                        }
                        break;
                    }
                }
            }
            #endregion
    
            public DataSet Query(CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters)
            {
                MySqlCommand cmd = new MySqlCommand();
                MySqlConnection conn = new MySqlConnection(ConnectionString);
                try
                {
                    PrepareCommand(conn, null, cmd, cmdType, cmdText, commandParameters);
                    MySqlDataAdapter adapter = new MySqlDataAdapter();
                    adapter.SelectCommand = cmd;
                    DataSet ds = new DataSet();
                    adapter.Fill(ds);
                    cmd.Parameters.Clear();
                    conn.Close();
                    return ds;
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
        }
    

    扩展类的目的是使用熟悉的原生ado.net的方式来避免趟EF的坑(未必有的)。 

    1)增 

    db.cashierlist.Add(bill);
                        try
                        {
                            db.Entry<cashierlist>(bill).State = System.Data.Entity.EntityState.Added;
                            db.SaveChanges();
                            result.Success = true;
                            result.Message = "操作成功!";
                            result.Result = bill;
                        }
                        catch (Exception ex)
                        {
                            var exx = ex.InnerException == null ? ex : ex.InnerException;
                            result.Message = exx.Message;
                        }
    

    这里好像就是需要写"db.Entry<T>(bill).State = System.Data.Entity.EntityState.Added",显式的标记为"System.Data.Entity.EntityState.Added",即新增状态。

    2)改和删好像跟以前一样的没啥说的。

    3)查

    var dbExists = db.ls_cashierlist.SqlQuery("select * from ls_cashierlist where cl_sn='" + bill.cl_sn + "'").FirstOrDefaultAsync().Result;

    toListAsync()/FirstOrDefaultAsync()/SingleAsync()等陌生方法给我带来了困惑。以前同步方式调用这些api习惯了,现在统统变成了支持异步的方法了。不深究,改成同步的方式就是取XXX方法的().Result就行了。

    2、关于.net连接mysql

    1)MYSQL某些字段日期时间类型如果是允许空值时且存了空值那么,MYSQL默认写的是“0000-00-00 00:00:00”这样子,这个其实在连接字符串里面有几个选项可以参考一下,就是"allowzerodatetime"和"convertzerodatetime".

    2)中文乱码,需要指定字符集,比如:characterset=utf8

    3、Http get或者post请求超时时间控制

    由于winform客户端在发起Http get或者post请求时刚开始设置的超时时间是5秒,后来发现请求在服务器端的webapi中处理时间比较久时,客户端就直接什么都不返回,自动被终止了,两边都没有异常。自动被超时时间这个参数处理掉了。

    还以为是那些个异步方法的使用有问题就是说webapi在返回值的时候没有等到异步方法返回就开始返回给客户端了。这是错误的,前面已经把异步改成同步了。

    后来增加超时时间就能正常返回了。记录一下,我自己能看懂就好

    还是老规矩,晒上几张图作为结束:

  • 相关阅读:
    unity3d 中文乱码解决方法——cs代码文件格式批量转化UTF8
    Unity SteamVR插件集成
    Unity3D Layer要点
    Unity利用Sapi进行windows语音开发
    Scratch入门课程(1)——把工具准备好
    【blockly教程】Blockly编程案例
    【blockly教程】第六章 Blockly的进阶
    【blockly教程】第五章 循环结构
    【blockly教程】第三章Blockly顺序程序设计
    【blockly教程】第四章 Blockly之选择结构
  • 原文地址:https://www.cnblogs.com/datacool/p/2016datacool_pos.html
Copyright © 2020-2023  润新知