zoukankan      html  css  js  c++  java
  • 笔记02-.Net基础2

    第五章:.Net常用基本类库

    String 常用方法1

    //bool Contains(String str):判断字符串对象是否包含给定的字符串。
    
    //bool StartsWith(String str):判断字符串对象是否以给定的字符串开始。
    
    //bool EndsWith(String str):判断字符串对象是否以给定的字符串结束。
    
                /*string s1 = "Hello";
                Console.WriteLine(s1.Contains("el"));
                Console.WriteLine(s1.Contains("abc"));
                 */
                /*
                Console.WriteLine(s1.StartsWith("He"));
                Console.WriteLine(s1.StartsWith("he"));
                 */
    
                /*
                string s = "http://www.rupeng.com";
                if (s.StartsWith("https://") &&
                    (s.EndsWith(".com") || s.EndsWith(".cn")))
                {
                    Console.WriteLine("合法网址");
                }
                else
                {
                    Console.WriteLine("非法网址");
                }*/
                /*
                string email = "3333@173.com";
                string username = "领导";
                if (email.EndsWith("@qq.com"))
                {
                    Console.WriteLine("本站不支持QQ邮箱");
                    Console.ReadKey();
                    return;
                }
                if (username.Contains("领导") || username.Contains("总书记"))
                {
                    Console.WriteLine("用户名请勿使用敏感词汇");
                    Console.ReadKey();
                    return;
                }*/
    View Code
    int Length:获取字符串的长度属性
    
    char ch = s[3];
    
    int IndexOf(char ch):返回指定字符在此字符串中第一次出现的索引
    
    int IndexOf(String str):返回指定字符串在此字符串中第一次出现的索引
    
    LastIndexOf:最后一次出现的位置。
    
    String Substring(int start):截取字符串。返回从指定位置开始截取后的字符串。
    
    String substring(int start,int length)截取字符串。返回从指定位置开始截取指定长度length的字符串。
    
                string s1 = "hellooabcdaabe";
                int i = s1.IndexOf('l');
                Console.WriteLine(i);
                Console.WriteLine(s1.IndexOf("ab"));
                Console.WriteLine(s1.LastIndexOf('l'));
    
                string s2 = s1.Substring(4);
                Console.WriteLine(s2);
                Console.WriteLine(s1.Substring(4,3));
    案例获取一个文件名的名称和扩展名部分:
    
                string filename = "[ADS-118]林志aaaaaa玲.avi";//
                int dotIndex = filename.IndexOf('.');//3
                string name = filename.Substring(0, dotIndex);
                Console.WriteLine(name);
                string ext = filename.Substring(dotIndex + 1);
                Console.WriteLine(ext);
    View Code
    String ToLower():把字符串变成小写;String ToUpper():把字符串变成大写
    
    String Replace(char oldChar,char newChar):用新的字符去替换指定的旧字符;String Replace(String oldStr,String newStr):用新的字符串去替换指定的旧字符串
    
    String trim():去除字符串两端空格, Trim(params char[] trimChars)去掉两端的给定字符。 TrimEnd、 TrimStart
    
    String是不可变的,因此上面的操作都是生成新的字符串对象,要用返回值去取新的字符串。
    
    String[] Split(...):重载方法很多,字符串按照分隔符切割。案例:把字符串用“,”分割
    View Code
    bool IsNullOrEmpty(string value):判断字符串是否为null或者是空字符串;
    
    bool Equals(string a, string b, StringComparison. OrdinalIgnoreCase):不区分大小写比较。案例:验证码
    
    string Join(string separator, params string[] value)把一个数组(集合)用分隔符separator连接为一个字符串。
    View Code

     StringBuilder

    1、使用反编译发现
    
    String s7="111"+"222"+"333"+"444"+"555"  
    
    会被优化为  String s7 = "111222333444555";
    
    但是String s6 = s1 + s2 + s3 + s4 + s5;就没那么幸运了,每次+都会生成一个String对象,当连接字符串比较多的时候就会产生临时字符串对象。
    
    2、使用StringBuilder拼接字符串则不会有临时字符串对象的问题:
    
    StringBuilder sb = new StringBuilder();
    
    sb.Append(s1);
    
    sb.Append(s2);
    
    sb.Append(s3);
    
    因为Append方法把this返回了,还可以sb.Append(s1).Append(s2).Append(s3);
    
    最后使用String s = sb.ToString()一次性生成拼接结果字符串即可
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CommonClassTest2
    {
        class Program
        {
            static void Main(string[] args)
            {
                /*
                string s1 = "aaa" +
                    +"aaaaa"+"bbb";
                Console.WriteLine(s1);
                 */
                string s1 = "aaa";
                string s2 = "bbb";
                string s3 = "ccc";
                string s4 = "ddd";
                string s5 = "afadsf";
                string s6 = s1 + s2 + s3 + s4 + s5;
    
                StringBuilder sb = new StringBuilder();
                /*
                sb.Append(s1);
                sb.Append(s2);
                sb.Append(s3);
                sb.Append(s4);
                sb.Append(s5);
                sb.Append(33);*/
               sb.Append(s1).Append(s2).Append(s3).Append(s4).Append(s5);
               sb.AppendLine("hello");
               sb.AppendLine("afasdfads");
    
                string s7 = sb.ToString();
                Console.WriteLine(s7);
    
                Person p1 = new Person();
                p1.Eat().Sleep().Dota();//链式编程 Jquery
                Console.ReadKey();
            }
        }
    
        class Person
        {
            public Person Eat()
            {
                Console.WriteLine("吃饭");
                return this;
            }
            public Person Sleep()
            {
                Console.WriteLine("睡觉");
                return this;
            }
            public Person Dota()
            {
                Console.WriteLine("打Dota");
                return this;
            }
        }
    }
    View Code

     可空的int(值类型)

    int等是值类型,不能为null。有时想表达“不知道数字是多少”的时候,用int任何值表示都不合适。
    
    C#中可以用“int?”表示“可空的int”。注意类型转换:
    
    int? i1=5;
    
    if(i1!=null)
    
    {
    
        int i= (int)i1;
    
    }
    
    也可以通过i1.HasValue判断是否为null、i1.Value来获得值。
    
    int? i = null;
    int? i2 = 3;
    if (i == null)
    {
        Console.WriteLine("i为null");
    }
    if (i2 != null)//i2.HasValue
    {
        //i2++;
        i2 = i2 + 3;
        //int i3 = i2;//把可能为null的int?赋值给
        //一定不为null的int
        int i3 = (int)i2;//i2.Value
        Console.WriteLine(i2);
    }
    long? l = null;
    View Code

    LED时钟

     private void timer1_Tick(object sender, EventArgs e)
            {
                string imgPath = 
        @"F:快盘NextBigNET课程5_不拖控件的.Net(.net常用基本类库)ledclock图片";
    
                DateTime now = DateTime.Now;
                int hour = now.Hour;
                int min = now.Minute;
                int sec = now.Second;
    
                int hourGe = hour % 10;//小时的个位
                int hourShi = hour / 10;//小时的十位
    
                int minGe = min % 10;
                int minShi = min / 10;
    
                int secGe = sec % 10;
                int secShi = sec / 10;
    
                pbHourShi.Load(imgPath+hourShi+".png");
                pbHourGe.Load(imgPath + hourGe + ".png");
    
                pbMinShi.Load(imgPath + minShi + ".png");
                pbMinGe.Load(imgPath + minGe + ".png");
    
                pbSecShi.Load(imgPath+secShi+".png");
                pbSecGe.Load(imgPath + secGe + ".png");
    
                //根据奇数秒还是偶数秒来决定“:”的闪烁
                if (sec % 2 == 0)
                {
                    pbColon1.Load(imgPath + "colon.png");
                    pbColon2.Load(imgPath + "colon.png");
                }
                else
                {
                    pbColon1.Load(imgPath + "empty.png");
                    pbColon2.Load(imgPath + "empty.png");
                }
            }
    View Code

     把阿拉伯数字转换为中文金额数字:123→壹佰贰拾三圆

    //附录:阿拉伯数字转换为中文
    
            static void Main(string[] args)
    
            {
    
                Console.WriteLine(ConvertInt("123"));
    
                Console.WriteLine(ConvertInt("1003"));
    
                Console.ReadKey();
    
            }
    
    
    
            public static string ConvertInt(string str)
    
            {
    
    
    
                string[] hanNums={"","","","","", "", "","","",""};
    
                string[] weiStrs={"","","","","","","","","","","","",""};
    
                int len = str.Length;
    
                int i;
    
                string tmpstr, rstr;
    
                rstr = "";
    
                for (i = 1; i <= len; i++)
    
                {
    
                    tmpstr = str.Substring(len - i, 1);
    
                    rstr = string.Concat(hanNums[Int32.Parse(tmpstr)] + weiStrs[i], rstr);
    
                }
    
                rstr = rstr.Replace("拾零", "");
    
                rstr = rstr.Replace("零拾", "");
    
                rstr = rstr.Replace("零佰", "");
    
                rstr = rstr.Replace("零仟", "");
    
                rstr = rstr.Replace("零萬", "");
    
                for (i = 1; i <= 6; i++)
    
                { 
    
                    rstr = rstr.Replace("零零", "");
    
                }
    
                rstr = rstr.Replace("零萬", "");
    
                rstr = rstr.Replace("零億", "");
    
                rstr = rstr.Replace("零零", "");
    
                rstr += "圆整";
    
    
    
                rstr = rstr.Replace("零圆", "");
    
                return rstr;
    
            }
    View Code

     异常的概念和捕获

    //1、异常的根类为Exception。异常类一般都继承自Exception
    
    //2、
    
    try
    
    {
    
        String s = null;
    
        s.ToString();
    
    }
    
    catch (NullReferenceException ex)
    
    {
    
        Console.WriteLine("为空"+ex.Message);
    
    } 
    
    //e就是发生异常的异常类对象,变量名只要不冲突就任意。
    
    //3、在异常处理中,一旦try里面有问题了。放弃try代码块中之后的代码,直接跳到catch里面执行。如果try代码后还有代码,则处理完catch后还会继续执行。
    
    //4、多个异常的处理
    
    try
    {
        int a = 10;
        int b = 0;
        Console.WriteLine(a / b);
        int[] arr = { 1, 2, 3 };
        Console.WriteLine(arr[3]);
    }
    catch (DivideByZeroException ae)
    {
        Console.WriteLine("除数不能为0");
    }
    catch (IndexOutOfRangeException ae)
    {
        Console.WriteLine("数组越界异常");
    }
    //可以catch住父类异常,这样就可以抓住所有子类异常了,但是强烈不建议大家这样做,特别是不要没理由的catch(Exception ex)
    
    //5、好的异常处理习惯:
    
    //不要只是把异常catch住什么都不做或者只是打印一下,这不是正常的“异常处理”。
    
    //不知道怎么处理就不要catch,出错比“把错误藏起爱”好。这样以为“不会出错了”,其实是把异常“吃掉了”,会让程序陷入逻辑混乱状态,要科学合理的处理异常(以后经常用就明白了)。
    View Code

     tryfinally

    try{
    //有可能有问题代码
    }catch(异常类型 异常变量){
    //处理方式
    }finally{
    //无论“有可能有问题代码”是否出错都要执行的代码
    }
    //注意:在vs调试的情况下,finally的执行可能看不到,因为vs会把异常抛出阻断代码执行,如果想验证是否都会进入finall,可以按CTRL+F5执行程序。
    View Code
    finally 的执行条件只有这一个。
    很可能在 try-catch 里直接 returnbreakcontinue ,导致跳出 try-catch 结构。你可能会想当然的认为既然我 return 了直接返回结果 finally 里的代码就不会执行。这是错误的!因为 finally 执行条件只是【try-catch 结构执行完】,即使 try-catchreturn 了,依然还是会先执行 finally 里的代码,然后才会真的 return。
    而你要是不用 finally,直接把最后要统一执行的代码放在 try-catch 外面,那 try-catchreturn,你的代码就不会被执行了。
    所以 finally 最常用的地方是在里面释放对象占用的资源的。
    View Code

     File类

    File是静态类(无法被new)中的主要静态方法:
    
    void Delete(string path):删除文件;
    
    bool Exists(string path):判断文件是否存在;
    
    string[] ReadAllLines(string path):将文本文件中的内容读取到string数组中;
    
    string ReadAllText(string path):将文本文件读取为一个字符串
    
    void WriteAllLines(string path, string[] contents):将string[]写入到文件中;
    
    void WriteAllText(string path, string contents):将字符串contents写入到文件path中。
    
    AppendAllText:向文件中附加内容;Copy复制文件;Move移动文件
    
    /*
    if(File.Exists(@"d:	empa.pnproj"))
    {
        File.Delete(@"d:	empa.pnproj");
    }*/
    
    /*
    string[] lines = File.ReadAllLines(@"d:	empmy.txt",
        Encoding.Default);
    for (int i = 0; i < lines.Length; i++)
    {
        Console.WriteLine("第"+i+"行:"+lines[i]);
    }*/
    /*
    String s = File.ReadAllText(@"d:	empmy.txt");
    Console.WriteLine(s);
        */
    // File.WriteAllText(@"d:	emp	est.txt", "欢迎你");
    //File.AppendAllText(@"d:	emp	est.txt", "afasfsafadsf");
    View Code

     Directory

    CreateDirectory(string path):创建文件夹全路径
    
    void Delete(string path, bool recursive):删除文件夹path, recursive表示是否也删除子文件及子文件夹。如果文件夹不为空, recursive=false,则抛异常;
    
    bool Exists(string path):判断文件夹是否存在
    
    EnumerateFiles、 EnumerateDirectories遍历文件和文件夹;
    
    // Directory.CreateDirectory(@"d:	empac");
    //Directory.Delete(@"d:	emp");//目录=文件夹,只能删除空文件夹
    //Directory.Delete(@"D:	emp
    edissessiontest", true); //递归删除
    
    IEnumerable<string> files1 =
        //Directory.EnumerateFiles(@"d:	emp");
        //Directory.EnumerateFiles(@"d:	emp","*.*",SearchOption.AllDirectories);
        Directory.EnumerateFiles(@"d:	emp", "*.avi", SearchOption.AllDirectories);
    IEnumerator<string> filesEnum1 = files1.GetEnumerator();
    while (filesEnum1.MoveNext())//在结果中向下移动一条
    {
        Console.WriteLine(filesEnum1.Current);//获得当前结果
    }
    View Code

     FileStream

    FileStream fs = new FileStream(@"d:	emp1.txt",FileMode.Create);
    byte[] bytes1 = Encoding.Default.GetBytes("你好
    ");
    //任何数据都是以byte为单位写入的。GetBytes获得字符串的byte表示形式
    fs.Write(bytes1,0,bytes1.Length);
    
    byte[] bytes2 = Encoding.Default.GetBytes("www.baidu.com");
    fs.Write(bytes2,0,bytes2.Length);//在上一个Write的结尾继续写入
    fs.Close();//一定要用完了关闭
    Stream写入的单位是byte(字节),char转换为byte时候,一个英文char转换为一个byte(对应的ASCII码),一个中文char转换为两个byte(*采用GBK编码时),试着输出bytes的长度。
    
    采用Default、UTF8、UTF32得到的字符串的byte[]长度不一样,因此说明不同类型编码在计算机中存储的不一样。用什么编码写入就用什么编码读取,否则会有乱码的问题。
    
    不要往C盘写,因为Win7、Win8默认普通程序没有权限读写C盘。
    View Code

     FileStream资源正确的释放Dispose

                FileStream f = null;
                FileStream f2 = null;//避免来不及创建就已经出异常(可能初始化就失败)
                try
                {
                    f = new FileStream("",FileMode.OpenOrCreate);//可能初始化异常
                    //很多代码
                    //如果这个过程里异常 f2还未初始化.
                    f2 = new FileStream("",FileMode.Append);
                }
                finally
                {
                    if(f!=null)
                    {
                        f.Dispose();
                    }
                    if (f2 != null)
                    {
                        f2.Dispose();
                    }
                }
    View Code

     using简化资源释放

    定义一个实现了IDisposable接口的类:
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace IOTest2
    {
        class MyFileStream:IDisposable
        {
            public MyFileStream()
            {
                //throw new Exception("初始化出错");
            }
    
            public void Write(int i)
            {
                throw new Exception("Write出错");
                Console.WriteLine("写入了"+i);
            }
    
            public void Dispose()
            {
                Console.WriteLine("Dispose被调用了,开始释放资源,虽然没什么可释放的");
            }
        }
    }
    
    
    使用:
    
    using (MyFileStream fs1 = new MyFileStream())
    {
        using (MyFileStream fs2 = new MyFileStream())
        {
            fs2.Write(333);
            fs1.Write(5);
        }
    }
    
    
    可以同时声明多个资源:
    
    using (MyFile f1 = new MyFile())
    
    using (MyFile f2 = new MyFile())
    
    {
    
    }
    
    using其实就是编译器简化的try……finally操作,通过ILSpy反编译成IL可以看出来。
    
    using只是try……finally,如果需要catch,只要catch就是了。
    View Code

     FileStream读取文本文件以及乱码问题(可以用StreamReader)

    using (FileStream fs = new FileStream(@"D:	emp1.txt", FileMode.Open))
    {
    
        byte[] bytes = new byte[4];
        //fs.Read(bytes, 0, bytes.Length);//每次读取4个字节,下次Read的时候再读取最多4个byte
        //返回值为真正读取的字节数
        int len;
        /*
        len = fs.Read(bytes, 0, bytes.Length);
        Console.WriteLine(len);
        len = fs.Read(bytes, 0, bytes.Length);
        Console.WriteLine(len);
        len = fs.Read(bytes, 0, bytes.Length);
        Console.WriteLine(len);
            */
    
        //判断是否已经读到了最后
        while ((len = fs.Read(bytes, 0, bytes.Length)) > 0)
        {
            //Console.WriteLine(len);
            //把byte数组转化为字符串
            //string s = Encoding.Default.GetString(bytes);
            string s = Encoding.Default.GetString(bytes, 0, len);
            Console.WriteLine(s);
        }
    
    }
    View Code

     FileStream实现文件的拷贝

    Stopwatch sw = new Stopwatch();
    sw.Start();
    using (Stream inStream = 
        new FileStream(@"d:	empDevCpp.zip", FileMode.Open))
    using (Stream outStream =
        new FileStream(@"e:	emp1.zip", FileMode.Create))
    {
        //byte[] bytes = new byte[100];//100字节
        //1024字节=1k,1024k=1m
        byte[] bytes = new byte[1024*50];//1M
        //缓冲区(buffer)的大小:过小:降低速度;过大:占用内存
        int len;
        while ((len = inStream.Read(bytes, 0, bytes.Length)) > 0)
        {
            outStream.Write(bytes, 0, len);//类似于GetString
        }
    }
    sw.Stop();
    Console.WriteLine("拷贝完成,耗时" + sw.ElapsedMilliseconds+"毫秒");
    View Code

     封装Copy流的方法并开发下载器

    static void Copy(Stream inStream, Stream outStream)
    {
        Copy(inStream, outStream, 1024 * 1024);
    }
    
    static void Copy(Stream inStream,Stream outStream,int bufferSize)
    {
        byte[] bytes = new byte[bufferSize];
        int len;
        while ((len = inStream.Read(bytes, 0, bytes.Length)) > 0)
        {
            outStream.Write(bytes, 0, len);
        }
    }
    
    using (Stream inStream = new FileStream(@"d:	empDevCpp.zip",FileMode.Open))
    using (Stream outStream = new FileStream(@"d:	emp1.zip", FileMode.Create))
    {
        Copy(inStream, outStream);
    }
    
    
    文件下载器:
    
    WebRequest req = WebRequest.Create("http://www.baidu.com/img/bd_logo1.png");
    using (WebResponse res = req.GetResponse())
    using (Stream inStream = res.GetResponseStream())
    using(Stream outStream = new FileStream(@"d:	emp2.png",FileMode.Create))
    {
        //inStream.CopyTo(
        Console.WriteLine(inStream.GetType());//Object o = new Person();
        //Copy(inStream, outStream);
        inStream.CopyTo(outStream);
    }
    View Code

     StreamReader和StreamWriter

    直接用Stream进行文本文件的读写会比较麻烦,因为要考虑文件的编码、中文字符等的问题。
    
    StreamReader、StreamWriter是用来读写字符流(character stream)的类,会帮着自动处理麻烦的问题。
    
    using (Stream outStream = 
        new FileStream(@"d:	emp1.txt", FileMode.Create))
    using(StreamWriter sw = 
        new StreamWriter(outStream,Encoding.Default))
    {
        sw.Write("你好a");
        sw.WriteLine("hehe");
        sw.WriteLine("1111");
    }
    using (Stream inStream = new FileStream(@"d:	emp1.txt",
        FileMode.Open))
    using (StreamReader reader =
        new StreamReader(inStream, Encoding.Default))
    {
        /*
        string s = reader.ReadToEnd();
        Console.Write(s);*/
        /*
        string s1 = reader.ReadLine();
        Console.WriteLine(s1);
    
        string s2 = reader.ReadLine();
        Console.WriteLine(s2);
            */
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            Console.WriteLine(line);
        }
    }
    View Code

     泛型List

    1、数组长度是固定的,List<T>可以动态增删内容。List<T>是泛型的,可以在声明的时候指定放什么类型的数据。
    
    List<int> list = new List<int>();
    
    list.Add(1);
    
    list.Add(2);
    
    list.AddRange(new int[] { 1, 2, 3, 4, 5, 6 });
    
    list.AddRange(list);//另一个list
    
    
    
    2、如何遍历?
    
    for (int i = 0; i < list1.Count; i++)
    
    {
    
        int num = list1[i];
    
        Console.WriteLine(num);
    
    }
    
    
    
    3int[] nums = list.ToArray(); //List泛型集合可以转换为数组
    
    List<string> listStr = new List<string>();
    
    string[] str = listStr.ToArray();
    View Code

     字典Dictionary

    Dictionary<string, string> dict = new Dictionary<string, string>();
    dict.Add("zs", "张三");
    dict.Add("ls", "李四");
    dict.Add("ww", "王五");
    dic["ls"] = "小赵";
    String s = dict["ww"];
    dict.ContainsKey();
    
    //<k,v>k是键的类型(根据谁查),v是值的类型(查什么)
    /*
    Dictionary<string, int> dict = new Dictionary<string, int>();
    dict.Add("abc", 123);//往字典中放数据(k,v)
    dict.Add("aaa", 222);
    int i = dict["abc"];//根据key从字典中查数据
    Console.WriteLine(i);
    Console.WriteLine(dict["aaa"]);*/
    
    /*
    Dictionary<string, string> dict = new Dictionary<string, string>();
    dict.Add("zs","张三");
    dict.Add("ls", "李四");
    // dict.Add("ls","李斯");// 如果key已经存在,则抛异常
    dict["ls"] = "李斯";//如果不存在key,则添加;如果存在则替换
    dict["ww"] = "王五";
                
    string name = dict["ls"];
    Console.WriteLine(dict.ContainsKey("ls"));
    Console.WriteLine(dict.ContainsKey("abc"));
    Console.WriteLine(name);
    View Code

     foreach

    注意:使用MoveNext()的方法讲解IEumerable只是在讲原理,实际开发中还是使用foreach
    
    
    
    除了使用for遍历,实现了IEumerable接口的对象还可以使用foreach遍历:
    
    string[] strs = { "fasdfa","fsadf","222"};
    foreach (string s in strs)
    {
        Console.WriteLine(s);
    }
    List<T>、 Dictionary<K,V> 等一切实现了IEumerable接口的对象都可以:
    
    Dictionary<string, object> dict = new Dictionary<string, object>();
    dict["rupeng"] = 888;
    dict["sina"] = "hehe";
    dict["baidu"] = true;
    foreach (KeyValuePair<string, object> kv in dict)
    {    
       Console.WriteLine(kv.Key+"="+kv.Value);
    }
    View Code

     ASCII介绍和char转换为int

    char和int各种转换
    
    namespace ConsoleApplication7
    {
        class Program
        {
            static void Main(string[] args)
            {
                /*
                Console.WriteLine(int.MaxValue);
                Console.WriteLine(int.MinValue);
    
                Console.WriteLine((int)char.MaxValue);//65535,显式转换,以便于匹配WriteLine的int类型的重载
                Console.WriteLine((int)char.MinValue);//0
    
                char c='a';
                Console.WriteLine(c);
                int i = c;//把char隐式转换为int(int范围比char大)
                //只要把char数据隐式或者显式转换为int,得到的int就是char的ASCII码
                Console.WriteLine(i);
                */
    
                /*
                char c = (char)97;
                Console.WriteLine(c);
    
                int i = 98;
                char c1 = (char)i;
                Console.WriteLine(c1);*/
    
                /*
                //'1'和1的区别
                char c1 = '1';//49
                int i1 = 1;//1
                int i2 = c1;
                Console.WriteLine(i2);
                Console.WriteLine(c1==i1);
                */
    
                /*
                char c1 = '0';
                char c2 = (char)(c1 + 2);//不能(char)c1+1
                Console.WriteLine(c2);
    
                char c3 = '5';
                char c4 = (char)(c3-2);
                Console.WriteLine(c4);
                */
    
                //Console.WriteLine(intToChar(5));
    
                //Console.WriteLine(charToInt('3'));
                Console.WriteLine(toUpper('d'));
    
                Console.ReadKey();
            }
    
            /// <summary>
            /// 把1转换为'1',2转换为'2'
            /// </summary>
            /// <param name="i"></param>
            /// <returns></returns>        
            static char intToChar(int i)
            {
                if (i < 0 || i > 9)
                {
                    throw new Exception("i必须在0-9之间");
                }
                return (char)('0' + i);//i=3
            }
    
            /// <summary>
            /// 把'1'转换为1
            /// </summary>
            /// <param name="c"></param>
            /// <returns></returns>
            static int charToInt(char c)
            {
                //'0','1'....'9'
                if (c < '0' || c > '9')//判断是否是数字字符
                {
                    throw new Exception("不是合法的数字字符");
                }
                return c - '0';
            }
    
            //'a'→'A'
            static char toUpper(char c)
            {
                if (c < 'a' || c > 'z')
                {
                    throw new Exception("不是小写字符");
                }
                //'a':97,'A':65;'c':99,'C':67
                //研究发现小写字符比大写字符大32
                //return c
                //return (char)(c - 32);
                return (char)(c-('a'-'A'));
            }
    
            //任务:写一个转换为小写的方法
        }
    }
    View Code

     第六章MYSQL

    安装运行

    绿色版MYSQL Server的安装:
    
    1)解压到没有中文、空格的文件夹下
    
    2)双击mysqld.exe,如果进程中有了mysqld.exe就ok了
    
    3)上面的方式需要每次重启电脑都要手动运行,特别是如果运行在服务器上,那么不能在登录前就启动。可以注册为系统服务:以管理员身份运行命令行,cd到mysql的bin文件夹,执行“mysqld -install”;卸载服务:mysqld -remove。
    
    注意在“mysqld”后面有个空格,不要写成“mysqld-install”
    
    
    
    绿色版MYSQL的用户名、密码都是:root
    View Code

     主键

    主键有两种选用策略:业务主键和逻辑主键。业务主键是使用有业务意义的字段做主键,比如身份证号、银行账号等;逻辑主键是使用没有任何业务意义的字段做主键,完全给程序看的,业务人员不会看的数据。因为很难保证业务主键不会重复(身份证号重复)、不会变化(帐号升位),因此推荐用逻辑主键。
    View Code

     外键

    B表中的字段指向A表的字段,叫外键.比如2个表关联主键

    建数据库立表的方法(表名命名:T_Student)

    1、根节点点右键“新建数据库”,数据库名字取得有意义,比如“study1”、字符集建议用"UTF-8"。复习:读写编码一致就不会乱码。
    
    2、在study1下的“表”节点下点右键“新建表”,“栏位”其实指的就是列(Column)/列,翻译的不好。Id(主键,潜规则的名称,int、不允许为空、点右键“主键”)、Name(varchar,长度为10,不允许为空)、Gender(bit,不允许为空),保存为“T_Persons”(我习惯的表命名规则T_名词复数)
    
    3、建表常见错误:列名/表名不要用可能的关键字、不要有空格(包括前后,一不小心输错试试)、不要有特殊字符
    
    双击生成的表,手工插入两条数据,注意点“提交”按钮
    
    4、MYSQL的存储引擎有很多,最常用的是InnoDB和MyISAM,MyISAM效率较高,但是不支持事务、外键约束等特性,因此一般建议用InnoDB,新版本默认也是InnoDB。怎么设:建表时“选项”→“引擎”。建好了如何看引擎:表上点右键“对象信息”。
    View Code

     MYSQL常用数据类型

    文本:
    
    CHAR(*):最多255个字节的定长字符串,它的长度必须在创建时指定
    
    VARCHAR(*):最多255个字节的可变长度字符串,它的长度必须在创建时指定
    
    TEXT:最大长度为64K字符的变长文本
    
    TINYTEXT:最大长度为255字符的变长文本
    
    MEDUIMTEXT:最大长度为16K字符的变长文本
    
    LONGTEXT:最大长度为4GB字符的变长文本
    
    
    
    整数(考虑数据取值后选择尽可能小的类型)
    
    tinyint:1字节。有符号值:-128 到127;无符号值:0到255
    
    smallint:2字节。有符号值:-32768 到32767;无符号值:0到65535
    
    mediumint:3字节。
    
    int:4字节
    
    bigint:8字节
    
    
    
    小数(需要指定长度和小数点,也就是显示宽度和小数位数):
    
    decimal:精确存储的小数,在内部用字符串存储,适合金额等要求精确的类型。别名:NUMERIC
    
    float:4字节,单精度。会近似存储(*),效率比decimal高。
    
    double:8字节,双精度。会近似存储(*),效率比decimal高。
    
    
    
    日期时间:
    
    DATE:4字节。范围:1000-01-01——9999-12-31
    
    TIME:3字节。范围:-838:59:59——838:59:59
    
    DATETIME:8字节。范围:1000-01-01 00:00:00——9999-12-31 23:59:59
    
    
    
    二进制大数据:
    
    TITYBLOB:最大长度为255字节
    
    BLOB:最大长度为64KB
    
    MEDIUMBLOB:最大长度为16MB
    
    LONGBLOB:最大长度为4GB
    View Code

     SQL简介

    1、SQL语句中字符串一般用单引号。
    
    2、SQL语句是大小写不敏感的。
    
    3、NavCat中找到执行SQL语句的地方“查询”→“新建查询”,编写SQL后点击【运行】执行SQL语句。
    
    补充:如果只想执行NavCat中编写的一部分代码,而不是执行全部代码,只要选中要执行的代码,点击鼠标右键,选择“运行已经选择的”即可。
    
    4、最简单的SQL:查看一个表的全部数据:select * from T_Persons
    
    5、简单的插入数据的SQL语句:INSERT INTO T_Persons(Id,Name,Age,Gender) VALUES(5,'Jim',20,1)
    
    Insert语句可以省略表名后的列名,但是强烈不推荐
    
    6、如果插入的行中有些字段的值不确定,那么Insert的时候不指定那些列即可。不“允许为空”的列在插入时不能省略。Navicat有一个bug:某些情况下没有给字段设定值,最后的结果竟然不是null,咱们不用管这个bug。
    
    7、自动递增/自增(Auto Increment):字段自增可以避免并发等问题,不要程序员代码控制自增。用自增字段在Insert的时候不用指定值。修改表结构的方法【设计表】。
    View Code

     UPDATE

    1、更新一个列:UPDATE T_Persons Set Age=30
    
    2、更新多个列: UPDATE T_Persons Set Age=30,Name='tom'
    
    3、表达式:UPDATE T_Persons Set Age=Age+1
    
    4更新一部分数据: UPDATE T_Persons Set Age=30 where Name='tom',用where语句表示只更新Name是'tom'的行,注意SQL中等于判断用单个=,而不是==5、Where中还可以使用复杂的逻辑判断UPDATE T_Persons Set Age=30 where Name='tom' or Age<25,or相当于Java中的||
    
    where (Age>20 and Age<30) or(Age=80)
    
    6、Where中可以使用的其他逻辑运算符:orandnot<>>=<=!=(或<>)等
    View Code

     Delete

    删除表中全部数据:DELETE FROM T_Persons。
    
    Delete 也可以带where子句来删除一部分数据:DELETE FROM T_Persons WHERE Age > 20
    
    Delete只是删除数据,表还在。(*)Drop table T_Persons
    View Code

    数据初始化和select语法1

    T_Employees初始数据:
    
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('DEV001','Tom',25,8300);
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('DEV002','Jerry',28,9300.80);
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('SALES001','John',23,5000);
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('SALES002','Kerry',28,6200);
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('SALES003','Stone',22,1200);
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('HR001','Jane',23,2200.88);
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('HR002','Tina',25,5200.36);
    INSERT INTO T_Employees(Number,Name,Age,Salary) VALUES('IT001','Smith',28,3900);
    INSERT INTO T_Employees(Number,Age,Salary) VALUES('IT002',27,2800);
    
    
    1、简单的数据检索 :SELECT * FROM T_Employees
    
    2、只检索需要的列 :SELECT Number FROM T_Employees 、SELECT Name,Age FROM T_Employees
    
    3、列别名:SELECT Number AS 编号,Name AS 姓名,Age AS Age111 FROM T_Employees  写不写AS都行
    
    4、计算列:SELECT Number 编号,Name 姓名,Age Age111,Age+10 十年后的年龄,1+1,now() FROM T_Employees
    
    5、使用where检索符合条件的数据:SELECT Name FROM T_Employees WHERE Salary<5000。故事:新员工的数据检索噩梦
    
    6、还可以检索不与任何表关联的数据:select 1+1;select now();
    View Code

     聚合函数

    1、SQL聚合函数:MAX(最大值)、MIN(最小值)、AVG (平均值)、SUM (和)、COUNT(数量)
    
    2、大于25岁的员工的最高工资 :SELECT MAX(Salary) FROM T_Employees WHERE Age>25 
    
    3、最低工资和最高工资:SELECT MIN(Salary),MAX(Salary) FROM  T_Employees
    
    4、大于25岁的员工人数:SELECT COUNT(*) FROM  T_Employees  WHERE Age>25 
    
    5、全体员工的工资总和平均工资:SELECT SUM(Salary),AVG (Salary) FROM  T_Employees
    View Code

     OrderBy

    1ORDER BY子句位于SELECT语句的末尾,它允许指定按照一个列或者多个列进行排序,还可以指定排序方式是升序(从小到大排列,ASC)还是降序(从大到小排列,DESC) 
    
    2、按照年龄升序排序所有员工信息的列表:SELECT * FROM  T_Employees ORDER BY Age ASC 
    
    3、按照年龄从大到小排序,如果年龄相同则按照工资从大到小排序 :SELECT * FROM  T_Employees ORDER BY Age DESC,Salary DESC
    
    4ORDER BY子句要放到WHERE子句之后 :SELECT * FROM T_Employees WHERE Age>23 ORDER BY Age DESC,Salary DESC 
    View Code

     Like

    通配符过滤使用LIKE 。
    
    1、单字符匹配的通配符为半角下划线“_”,它匹配单个出现的字符。以任意字符开头,剩余部分为“erry” :SELECT * FROM T_Employees WHERE Name LIKE '_erry' 
    
    2、多字符匹配的通配符为半角百分号“%”,它匹配任意次数(零或多个)出现的任意字符。 “k%”匹配以“k”开头、任意长度的字符串。检索姓名中包含字母“n”的员工信息 :SELECT * FROM T_Employees WHERE Name LIKE '%n%' 
    
    3、Like性能较差,很容易造成全表扫描,谨慎使用。后面会讲数据库优化(索引等),项目中做搜索用全文检索。
    View Code

     null

    1、数据库中,一个列如果没有指定值,那么值就为null,数据库中的null表示“不知道”,而不是表示没有。因此select null+1结果是null,因为“不知道”加1的结果还是“不知道”。
    
    2SELECT * FROM T_Employees WHERE NAME=nullSELECT * FROM T_Employees WHERE NAME!=null ;
    
    都没有任何返回结果,因为数据库也“不知道”。
    
    3、提问:如果T_Employees表中Name列的值是null的话,那么下面查询结果是什么?Select Name+"a" FROM T_Employees 。
    
    
    
    答案:还是null,因为null和任何的东西做任何的运算都是null,null+"a"还是null。
    
    4、SQL中使用is nullis not null来进行空值判断: 
    
    SELECT * FROM T_Employees WHERE NAME is nullSELECT * FROM T_Employees WHERE NAME is not null
    View Code

     LIMIT

    1、LIMIT关键字用来限制返回的结果集, LIMIT放在SELECT语句的最后位置,语法为“LIMIT  首行行号,要返回的结果集的最大数目” 。比如下面的SQL语句将返回Name不为空的、按照工资降序排列的从第二行开始(行号从0开始)的最多五条记录:
    
    SELECT * FROM T_Employees
    
    where Name is not null 
    
    ORDER BY Salary DESC  
    
    LIMIT 2,5
    
    
    
    2、limit一定要放到所有的语句的最后。
    View Code

     Groupby分组查询

    1、数据分组用来将数据分为多个逻辑组,从而可以对每个组进行聚合运算。SQL语句中使用GROUP BY子句进行分组,使用方式为“GROUP BY  分组字段”。分组语句一般和聚合函数一起使用,GROUP BY子句负责将数据分成逻辑组,而聚合函数则对每一个组进行统计计算。
    
    2、查看公司员工有哪些年龄段的:
    
    SELECT Age FROM T_Employees GROUP BY Age 
    
    将Age相同的数据行放到一组,分组后的数据可以看作一个临时的结果集,而SELECT  Age语句则取出每组的Age字段的值,这样我们就得到上表的员工年龄段表了。
    
    3、如果SELECT语句有WHERE子句,则GROUP BY子句必须放到WHERE语句的之后。
    
    4GROUP  BY子句将检索结果划分为多个组,每个组是所有记录的一个子集。上面的SQL例子在执行的时候数据库系统将数据分成了下面的分组:
    
    5、
    
    分组后就可以对组内的数据采用聚合函数进行统计了:
    
    1)计算每个分组中的员工平均工资
    
    SELECT Age,AVG(Salary) FROM T_Employees
    
    GROUP BY Age
    
    2)查看每个年龄段的员工的人数:
    
    SELECT Age,COUNT(*)  FROM T_Employees
    
    GROUP BY Age
    View Code

     left join

    初始数据:
    
    INSERT INTO T_Customers(Id,Name,Age)
    VALUES(1,'TOM',21);
    INSERT INTO T_Customers(Id,Name,Age)
    VALUES(2,'MIKE',24);
    INSERT INTO T_Customers(Id,Name,Age)
    VALUES(3,'JACK',30);
    INSERT INTO T_Customers(Id,Name,Age)
    VALUES(4,'TOM',25);
    INSERT INTO T_Customers(Id,Name,Age)
    VALUES(5,'LINDA',30);
    
    INSERT INTO T_OrderTypes(Id,Name)
    VALUES(1,'现货订单');
    INSERT INTO T_OrderTypes(Id,Name)
    VALUES(2,'预订订单');
    INSERT INTO T_OrderTypes(Id,Name)
    VALUES(3,'预购订单');
    INSERT INTO T_OrderTypes(Id,Name)
    VALUES(4,'内部');
    
    INSERT INTO T_Orders(Id,Number,Price,CustomerId, TypeId)
    VALUES(1,'K001',100,1,1);
    INSERT INTO T_Orders(Id,Number,Price,CustomerId, TypeId)
    VALUES(2,'K002',200,1,1);
    INSERT INTO T_Orders(Id,Number,Price,CustomerId, TypeId)
    VALUES(3,'T003',300,1,2);
    INSERT INTO T_Orders(Id,Number,Price,CustomerId, TypeId)
    VALUES(4,'N002',100,2,2);
    INSERT INTO T_Orders(Id,Number,Price,CustomerId, TypeId)
    VALUES(5,'N003',500,3,4);
    INSERT INTO T_Orders(Id,Number,Price,CustomerId, TypeId)
    VALUES(6,'T001',300,4,3);
    INSERT INTO T_Orders(Id,Number,Price,CustomerId, TypeId)
    VALUES(7,'T002',100,1,1);
    
    
    1、查询每张订单的订单号、价格、对应的客户姓名以及客户年龄
    
    SELECT o.Number,o.Price,c.Name,c.Age
    
    FROM T_Orders o
    
    LEFT JOIN T_Customers c
    
    ON o.CustomerId=c.Id
    
    2、添加where语句(显示价格>=150元的订单)
    
    SELECT o.Number,o.Price,o.CustomerId,
    
    c.Name,c.Age  FROM T_Orders o
    
    LEFT JOIN T_Customers c  ON o.CustomerId=c.Id
    
    WHERE o.Price>=150
    
    3、可以join多张表:
    
    SELECT o.Number 订单号,o.Price 价格, c.Name 客户姓名,c.Age 客户年龄,t.Name 订单类型  FROM T_Orders o
    
    LEFT JOIN T_Customers c  ON o.CustomerId=c.Id
    
    LEFT JOIN T_OrderTypes t ON o.TypeId=t.Id
    View Code

     外键约束

    1、如果删除/更新T_Customers一行记录,那么就可能会导致T_Orders中存在CustomerId为非法值的数据,使得程序逻辑错误。一般不会更新主键Id的值,所以谈外键约束的时候只谈“删除T_Customers时”。
    
    2、外键约束:当删除T_Customers中一条数据的时候,如何处理T_Orders等存在指向T_Customers外键的行。外键约束建立在外键字段***Id的表上(t_orders)。
    
    3、建外键约束的方法:新建或者修改表的时候“外键”→“添加外键”。名:自动命名即可;栏位名:CustomerId;参考表:t_customers;外栏位名:Id;删除时、更新时:一般默认RESTRICT(CASCADE:删除T_Customers一行时把它的订单也删除了;SET NULL:删除T_Customers一行时把它的订单CustomerId设置为NULL;NO ACTION/RESTRICT:拒绝删除)。
    
    4、有的公司不习惯建外键,而是通过程序进行数据合法性控制,对于初学者先不建议这样,都把外键加上。
    View Code

     第七章ADO.NET

    ADO.NET是.NET中提供的标准访问数据库的接口,访问不同的DBMS的底层方法是不一样的,ADO.NET把访问数据库的方法进行了统一,访问MYSQL,Oracle,SQLServer等不同的数据库的用法几乎一模一样.

    ADO.NET是规范,被不同的数据库厂商提供ADO.NET的实现,称之为ADO.NET驱动,每个厂商提供的驱动可以用来操作自己的数据库.

    MYSQL的.Net驱动mysql-connector-net-***.msi下载地址:
    
    1)https://dev.mysql.com/get/Downloads/Connector-Net/mysql-connector-net-6.9.9.msi 
    
    
    
    新建项目,添加引用→“扩展”,添加Mysql.Data;如果是直接解压版,然后直接添加对MySql.Data.dll文件的引用;
    
    using (MySqlConnection conn =
        new MySqlConnection("Server=localhost;Database=study1;uid=root;pwd=root;Charset=utf8"))
    using (MySqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();//一定要在执行前Open数据库连接
        cmd.CommandText = "Insert into T_Users(UserName,Password) values('中国人','123')";
        int rowCount = cmd.ExecuteNonQuery();
        Console.WriteLine("受影响的行数"+rowCount);
    }
    解释一下代码:
    
    MySqlConnection、MySqlCommand实现了IDisposable接口,因此使用using进行资源释放;
    
    "Server=localhost;Database=study1;uid=root;pwd=root;Charset=utf8"叫连接字符串,Server是Mysql服务器的地址,Database是连接的数据库,uid、pwd是用户名和密码,采用utf8编码。
    
    conn.Open():在执行MySqlCommand之前一定要先打开数据库连接,否则会报错。
    
    ExecuteNonQuery是执行Update、Insert、Delete等非查询语句,返回值为受影响的行数。
    
    
    
    如果运行的时候报错AccessViolationException,一般是由于你电脑装了一些乱七八糟的软件把winsock组件搞坏了的原因,你以管理员模式运行命令行,然后执行 netsh winsock reset 然后重启电脑试试。
    View Code

     执行insert语句

    using (MySqlConnection conn =
        new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
    using(MySqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "Insert into T_Users(UserName,Password) values('aaa','123')";
        int rc = cmd.ExecuteNonQuery();
        Console.WriteLine("插入成功,影响行数"+rc);
    }
    ExecuteNonQuery是执行Update、Insert、Delete等非查询语句,返回值为受影响的行数。
    View Code

     ExecuteScalar

    ExecuteScalar:执行查询,并返回查询所返回的结果集中第一行的第一列,忽略其他行列。一般用来简单的获得只有一行一列的查询结果的值。
    
    案例1:
    
    cmd.CommandText = "Select count(*) from T_Users";
    
    long count = (long)cmd.ExecuteScalar();
    
    案例2:
    
    cmd.CommandText = "Select Password from T_Users where UserName='admin'";
    
    string pwd = (string)cmd.ExecuteScalar();
    
    if (string.IsNullOrEmpty(pwd))
    
    {   
    
       Console.WriteLine("找不到admin");
    
    }
    
    else
    
    {    
    
       Console.WriteLine("admin的密码:" + pwd);
    
    }
    View Code

     ExecuteReader

    cmd.CommandText = "select * from T_Users";
    using (MySqlDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            long id = reader.GetInt64("Id");
            string userName = reader.GetString("UserName");
            string password = reader.GetString("Password");
    
            Console.WriteLine("id=" + id + ";UserName=" + userName + ";Password=" + password);
        }
    }
    注意:Reader的遍历、读取时需要Connection保持连接,如果关闭了Connection,使用Reader会出错。
    
    也可以根据列序号获取列的值,效率略高,不过程序不容易读;通过reader.GetOrdinal("Age")获得列名对应的列序号。
    View Code

     SQL注入漏洞攻击,,开发一定得注意

     参数化查询

    /*
    using(MySqlConnection conn = new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
    using (MySqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "Insert into @p(UserName,Password) values(@un,@pwd)";
        cmd.Parameters.Add(new MySqlParameter { ParameterName = "@p", Value = "t_users" });
        cmd.Parameters.Add(new MySqlParameter { ParameterName="@un",Value="rueng"});
        cmd.Parameters.Add(new MySqlParameter { ParameterName="@pwd",Value="123456"});
        cmd.ExecuteNonQuery();
    }*/
    
    /*
    using(MySqlConnection conn = new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
    using (MySqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "Insert into T_Users(UserName,Password,Age) values(@un,@pwd,@Age)";
        cmd.Parameters.Add(new MySqlParameter("@un","test1"));
        cmd.Parameters.Add(new MySqlParameter("@pwd", "321"));
    
        //int i = 0;
        //cmd.Parameters.Add(new MySqlParameter("@Age", i));
        // cmd.Parameters.Add(new MySqlParameter("@Age", 0));
        cmd.Parameters.Add(new MySqlParameter("@Age",(object)0));
        cmd.ExecuteNonQuery();
    }*/
    View Code

     读取数据库中的null值

    使用IsDBNull获取指定序号的列的值是否为null
    
    int? age=null;
    
    if (!reader.IsDBNull(reader.GetOrdinal("Age")))
    
    {
    
        age = reader.GetInt32("Age");
    
    }
    
    using (MySqlConnection conn =
    new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
    using (MySqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "select * from T_Users;";
        using (MySqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                string username = reader.GetString("UserName");
            // string password = reader.GetString("Password");
                string password;
                if (reader.IsDBNull(reader.GetOrdinal("Password")))
                {
                    password = null;
                }
                else
                {
                    //GetString/GetInt32 无法读取数据库中的null值
                    //需要提前用IsDBNull判断
                    password = reader.GetString("Password");
                }
                int? age;
                if (reader.IsDBNull(reader.GetOrdinal("Age")))
                {
                    age = null;
                }
                else
                {
                    age = reader.GetInt32("Age");
                }
            // int age = reader.GetInt32("Age");
                Console.WriteLine("用户名:"+username+";密码:"+
                    (password==null?"不知道密码":password)+";年龄:"+
                    (age==null?"不知道年龄":age.ToString()));
            }
        }
    }
    View Code

     离线结果集入门

    DataReader是服务器结果集游标的体现,所有查询出来的数据都在MySQL服务器上。好处是:当查询结果数据量大的时候避免占用本地内存。不过大部分项目中都会避免大查询结果,因此缺点就明显了:读取的时候必须保持Connection,不仅用起来麻烦,而且会较长时间占用MySQL服务器的连接资源。
    
    DataSet是一个离线结果集容器,它把结果数据放到本地内存中。因为查询结果可能会包含多个表,因此DataSet包含若干DataTable(ds.Tables)、DataTable包含若干DataRow(dt. Rows)。
    
    用法1:
    
    DataSet ds = new DataSet();
    MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
    adapter.Fill(ds);
    DataTable table = ds.Tables[0];
    
    
    DataSet 可以盛放多个查询结果集到DataTable ;DataAdapter还可以对结果进行傻瓜化更新、删除、修改。我们一般查询结果集就一个DataTable, DataAdapter的傻瓜化更新不适合于正式的项目,因此有更简单的用法
    
    DataTable dt = new DataTable();
    
    dt.Load(reader);
    
    把DataTable声明到using外,using外再使用查询结果。
    
    遍历DataTable:
    
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        DataRow row = dt.Rows[i];
        string name = row.IsNull("Name")?null:(string)row["Name"];//NULL处理
        Console.WriteLine("name"+name);
    }
    
    
    案例代码:
    
    /*
        using (MySqlConnection conn =
        new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
        using (MySqlCommand cmd = conn.CreateCommand())
        {
            conn.Open();
            cmd.CommandText = "select * from t_users";
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                DataTable dt = new DataTable();
                dt.Load(reader);
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    DataRow row = dt.Rows[i];
                    int id = (int)row["Id"];//下标方式获得是object
                    string username = (string)row["UserName"];
    
                    //做很复杂的io操作,把username存到文件中
                    //这样就会长期占据Connection
    
                // object obj = row["Password"];
                    //if(row["Password"]==DBNull.Value)//返回的不是null,而是DBNull
                             
                    //string password = (string)row["Password"];
                    //int age = (int)row["Age"];
                    string password = row.IsNull("Password") ? null : (string)row["Password"];
                    int? age = row.IsNull("Age") ? (int?)null : (int)row["Age"];
    
                    Console.WriteLine("id=" + id + ";Username=" + username
                        +";username="+username+";age="+age);
                }
            }
        }*/
    
    /*
    DataTable table  = new DataTable();
    using (MySqlConnection conn =
        new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
    using (MySqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "select * from t_users";
        using (MySqlDataReader reader = cmd.ExecuteReader())
        {
            table.Load(reader);//加载到table中
        }
    }
    
    for (int i = 0; i < table.Rows.Count; i++)
    {
        DataRow row = table.Rows[i];
        int id = (int)row["id"];
        string username = (string)row["UserName"];
        Console.WriteLine(id+":"+username);
    }
    */
    View Code

     MySqlHelper

    连接字符串一般配置到App.config(网站是Web.config)中的<connectionStrings>段中
    
    使用ConfigurationManager类(添加对System.Configuration的引用)读取
    
    string connstr =
    
               ConfigurationManager.ConnectionStrings["connstr"].ConnectionString
    
    注意:
    
    1、注意不要修改App.config的名字为App1.config之类的,必须叫App.config(网站是Web.config)
    
    2、配置文件中只能有一个connectionstrings段,不能配置多个
    
    3、一定要保证代码中的名字和配置文件中的名字一致(初学者容易犯错的,一般提示“初始化代码错误”这个错误就是因为两者名字不一致造成的)
    
    
    
    using MySql.Data.MySqlClient;
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ADONETTest2
    {
        class MySqlHelper
        {
            private static readonly string connstr =
                ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
    
            public static MySqlConnection CreateConnection()
            {
                //using (MySqlConnection conn = new MySqlConnection(connstr))
                MySqlConnection conn = new MySqlConnection(connstr);
                conn.Open();
                return conn;
            }
    
            public static int ExecuteNonQuery(MySqlConnection conn, string sql,
                params MySqlParameter[] parameters)
            {
                using (MySqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    /*
                    foreach (MySqlParameter p in parameters)
                    {
                        cmd.Parameters.Add(p);
                    }*/
                    cmd.Parameters.AddRange(parameters);
                    return cmd.ExecuteNonQuery();
                }
            }
    
            public static int ExecuteNonQuery(string sql,
                params MySqlParameter[] parameters)
            {
                using (MySqlConnection conn = CreateConnection())
                {
                    return ExecuteNonQuery(conn, sql, parameters);
                }
            }
    
            public static object ExecuteScalar(MySqlConnection conn, string sql,
                params MySqlParameter[] parameters)
            {
                using (MySqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    return cmd.ExecuteScalar();
                }
            }
    
            public static object ExecuteScalar(string sql,
               params MySqlParameter[] parameters)
            {
                using (MySqlConnection conn = CreateConnection())
                {
                    return ExecuteScalar(conn, sql, parameters);
                }
            }
    
            public static DataTable ExecuteQuery(MySqlConnection conn, string sql,
               params MySqlParameter[] parameters)
            {
                DataTable table = new DataTable();
                using (MySqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    using (MySqlDataReader reader = cmd.ExecuteReader())
                    {
                        table.Load(reader);                    
                    }
                }
                return table;
            }
    
            public static DataTable ExecuteQuery(string sql,
               params MySqlParameter[] parameters)
            {
                using (MySqlConnection conn = CreateConnection())
                {
                    return ExecuteQuery(conn, sql, parameters);
                }
            }
        }
    }
    View Code

     获取自动增长字段的值

    1、使用LAST_INSERT_ID()获取“最后一次插入的自动递增列的值”
    
    2、需要注意Insert语句和select LAST_INSERT_ID()一定要在要在同一个连接中。
    
    using (MySqlConnection conn = MySqlHelper.CreateConnection())
    {
        MySqlHelper.ExecuteNonQuery(conn,
            "insert into t_users(UserName,Password) values('我几时我','123')");
        object o = MySqlHelper.ExecuteScalar(conn, "select Last_Insert_Id()");
        //Last_Insert_Id()是获取当前连接中,最近一次自动递增字段的值
        ulong id = (ulong)o;//无符号的long
        Console.WriteLine(id);
    }
    可以Insert、LAST_INSERT_ID()在同一个连接中单独执行,也可以把LAST_INSERT_ID()放到insert语句后面用;分割(使用ExecuteScalar执行即可)
    
    ulong id = (ulong)MySqlHelper.ExecuteScalar("insert into t_users(UserName,Password) values('我几时我','123');select last_insert_id()");
    Console.WriteLine(id);
    View Code

     事物的原子性

    事务的几个关键环节:
    
    1)要在一个连接中;
    
    2)启动事务:MySqlTransaction tx = conn.BeginTransaction(); 
    
    3)操作结束后执行tx.Commit() 提交事务;
    
    4)如果执行出错,则tx.Rollback()回滚(当前事务的操作全部取消)。
    
     MySqlTransaction tx = conn.BeginTransaction();
        try
        {
            MySqlHelper.ExecuteNonQuery(conn, "Update t_accounts Set Amount=Amount-1000 where Number='0001'");
            string s = null;        s.ToLower();
            MySqlHelper.ExecuteNonQuery(conn, "Update t_accounts Set Amount=Amount+1000 where Number='0002'");
            tx.Commit();
        }
        catch (Exception ex)
        {
            tx.Rollback();
         }
    View Code

    SQLServer2008R2

    1、ADO.Net如何连接SQLServer:SQLServer驱动.Net内置(亲生的);把MySqlConnection换成SqlConnection,MySql***换成Sql***2、连接字符串: 
    
     server=ip;user id=sa;password=密码;database=db1
    
    3、SQLHelper:把MySql查找替换成Sql就可以了。
    
    4、获得自动增长列的值:Insert into t1(...) output inserted.Id values(.........)
    
    5、(*)如果基于接口编程,只要改动CreateConnection就可以(查询参数以Dictionary<string,object>传递;如果使用Provider,连代码都不用改,改配置文件即可。
    
    6、需要特别注意:SqlServer的事务和mysql事务使用有一点不一样的地方是“需要把BeginTransaction返回的SqlTransaction对象赋值给SqlCommand的Transaction属性”
    View Code

     SQLHelper

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace SQLHelper
    {
    
        class SQLHelper
        {
            private static readonly string connStr = ConfigurationManager.ConnectionStrings["heiyo"].ConnectionString;
            public static SqlConnection CreateConnection()
            {
                SqlConnection conn = new SqlConnection(connStr);
                conn.Open();
                return conn;
            }
    
            public static int ExecuteNonQuery(SqlConnection conn, string sql, params SqlParameter[] parameters)
            {
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    return cmd.ExecuteNonQuery();
                }
            }
            public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters)
            {
                using (SqlConnection conn = CreateConnection())
                {
                    return ExecuteNonQuery(conn, sql, parameters);
                }
            }
            public static object ExecuteScalar(SqlConnection conn, string sql, params SqlParameter[] parameters)
            {
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    return cmd.ExecuteScalar();
                }
            }
            public static object ExecuteScalar(string sql, params SqlParameter[] parameters)
            {
                using (SqlConnection conn = CreateConnection())
                {
                    return ExecuteScalar(conn, sql, parameters);
                }
            }
            public static DataTable ExecuteQuery(SqlConnection conn, string sql, params SqlParameter[] parameters)
            {
                DataTable table = new DataTable();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        table.Load(reader);
                    }
                }
                return table;
            }
            public static DataTable ExecuteQuery(string sql, params SqlParameter[] parameters)
            {
                DataTable table = new DataTable();
                using (SqlConnection conn = CreateConnection())
                {
                    return ExecuteQuery(conn, sql, parameters);
                }
    
            }
        }
    }
    View Code

    varchar,不带中文,nvarchar带中文,自增主键用bigint

    DBHelper通过接口编程使用ADO.Net感受多态的强大

    using MySql.Data.MySqlClient;
    using System;
    using System.Data;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Data.SqlClient;
    
    namespace DBHelper
    {
        class DBHelper
        {
            private static readonly string connStr = ConfigurationManager.ConnectionStrings["a1"].ConnectionString;
            public static IDbConnection CreateConnection()
            {
                SqlConnection conn = new SqlConnection(connStr);
               // MySqlConnection conn = new MySqlConnection(connStr);
                conn.Open();
                return conn;
            }
    
            public static int ExecuteNonQuery(IDbConnection conn, string sql,Dictionary<string,object> parameters)
            {
                using (IDbCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    foreach (KeyValuePair<string,object> kvp in parameters)
                    {
                        IDbDataParameter parameter = cmd.CreateParameter();
                        parameter.ParameterName = kvp.Key;
                        parameter.Value = kvp.Value;
                        cmd.Parameters.Add(parameter);
                    }
                    return cmd.ExecuteNonQuery();
                }
            }
            public static int ExecuteNonQuery(string sql, Dictionary<string, object> parameters)
            {
                using (IDbConnection conn = CreateConnection())
                {
                    return ExecuteNonQuery(conn, sql, parameters);
                }
            }
            public static object ExecuteScalar(IDbConnection conn, string sql, Dictionary<string, object> parameters)
            {
                using (IDbCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    foreach (KeyValuePair<string, object> kvp in parameters)
                    {
                        IDbDataParameter parameter = cmd.CreateParameter();
                        parameter.ParameterName = kvp.Key;
                        parameter.Value = kvp.Value;
                        cmd.Parameters.Add(parameter);
                    }
                    return cmd.ExecuteScalar();
                }
            }
            public static object ExecuteScalar(string sql, Dictionary<string, object> parameters)
            {
                using (IDbConnection conn = CreateConnection())
                {
                    return ExecuteScalar(conn, sql, parameters);
                }
            }
            public static DataTable ExecuteQuery(IDbConnection conn, string sql, Dictionary<string, object> parameters)
            {
                DataTable table = new DataTable();
                using (IDbCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    foreach (KeyValuePair<string, object> kvp in parameters)
                    {
                        IDbDataParameter parameter = cmd.CreateParameter();
                        parameter.ParameterName = kvp.Key;
                        parameter.Value = kvp.Value;
                        cmd.Parameters.Add(parameter);
                    }
                    using (IDataReader reader = cmd.ExecuteReader())
                    {
                        table.Load(reader);
                    }
                }
                return table;
            }
            public static DataTable ExecuteQuery(string sql, Dictionary<string, object> parameters)
            {
                DataTable table = new DataTable();
                using (IDbConnection conn = CreateConnection())
                {
                    return ExecuteQuery(conn, sql, parameters);
                }
    
            }
        }
    }
    View Code

     Like和In中查询参数的问题

     Console.WriteLine("请输入要查询的姓名");
    
                string name = Console.ReadLine();
    
                //'%@Name%'是一个整体,无法“部分当成查询参数”
    
               //DataTable dt =  SqlHelper.ExecuteQuery("select * from T_Persons where Name like '%@Name%'",
    
                //DataTable dt = SqlHelper.ExecuteQuery("select * from T_Persons where Name like '%'+@Name+'%'",
    
                    //new SqlParameter("@Name",name));
    
                DataTable dt = SqlHelper.ExecuteQuery("select * from T_Persons where Name like @Name",
    
                    new SqlParameter("@Name","%"+name+"%"));
    
               foreach (DataRow row in dt.Rows)
    
               {
    
                   Console.WriteLine(row["Name"]);
    
               }
    
    
    
               string line =  Console.ReadLine();
    
                
    
                foreach(char ch in line)
    
                {
    
                    if(!char.IsDigit(ch)&&ch!=',')
    
                    {
    
                        Console.WriteLine("输入非法");
    
                        Console.ReadKey();
    
                        return;
    
                    }
    
                }
    
    
    
                //DataTable dt = SqlHelper.ExecuteQuery("select * from T_Persons where Age in(@Age)",
    
                  //  new SqlParameter("@Age",line));
    
              // DataTable dt = SqlHelper.ExecuteQuery("select * from T_Persons where Age in(" + line+")");
    
                DataTable dt = SqlHelper.ExecuteQuery("exec('select * from T_Persons where Age in('+@Age+')')",
    
                    new SqlParameter("@Age",line));
    
               foreach (DataRow row in dt.Rows)
    
               {
    
                   Console.WriteLine(row["Name"]+"="+row["Age"]);
    
               }
    View Code

     SQLServer中事物

    using (SqlConnection conn = new SqlConnection(connstr))
    
                {
    
                    conn.Open();
    
                    using (SqlTransaction tx = conn.BeginTransaction())
    
                    {
    
    
    
                        try
    
                        {
    
                            //using是保证资源一定会被回收的,离开using范围后自动调用Dispose方法(无论是否有异常)
    
                            //using==try...finally...
    
                            //using不会进行异常的catch
    
                            using (SqlCommand cmd1 = conn.CreateCommand())
    
                            using (SqlCommand cmd2 = conn.CreateCommand())
    
                            {
    
                                cmd1.Transaction = tx;//在SQLServer中必须把BeginTransaction返回的对象赋值给SqlCommand的
    
                                //Transaction属性
    
                                cmd1.CommandText = "insert into T_Persons(Name,Age) values('a',1)";
    
                                cmd1.ExecuteNonQuery();
    
    
    
                                cmd2.Transaction = tx;
    
                                cmd2.CommandText = "insert into T_Persons(Name,Age) values('b',2)";
    
                                cmd2.ExecuteNonQuery();
    
                            }
    
                            tx.Commit();
    
                        }
    
                        catch (Exception ex)
    
                        {
    
                            tx.Rollback();
    
                        }
    
                    }
    
                }
    View Code

     SqlBulkCopy 批量插入

    DataTable dt = new DataTable();
    
                 dt.Columns.Add("Name");
    
                 dt.Columns.Add("Age");
    
                 for (int i = 0; i < 80000; i++)
    
                 {
    
                    DataRow row =  dt.NewRow();
    
                    row["Name"] = "aa" + i;
    
                    row["Age"] = i * i;
    
                    dt.Rows.Add(row);
    
                 }
    
    
    
                 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connstr))
    
                 {
    
                     bulkCopy.DestinationTableName = "T_Persons";
    
                     bulkCopy.ColumnMappings.Add("Name", "Name");
    
                     bulkCopy.ColumnMappings.Add("Age", "Age");
    
                     bulkCopy.WriteToServer(dt);
    
                 }
    View Code

     MySQL的批量数据插入

    Stopwatch sw = new Stopwatch();
    
                sw.Start();
    
                using (MySqlConnection conn = new MySqlConnection("server=127.0.0.1;database=study1;uid=root;pwd=root"))
    
                {
    
                    conn.Open();
    
                    using (MySqlCommand cmd = conn.CreateCommand())
    
                    {
    
                        //一条SQL数据的长度有限
    
                        //拼接出1000条数据就批量插入一次
    
                        List<string> listSql = new List<string>();
    
                        for (int i = 0; i < 100000; i++)
    
                        {
    
                            listSql.Add("('test"+i+"','"+i+"')");
    
                            if (listSql.Count > 1000)
    
                            {
    
                                string sql = "insert into t_users(UserName,Password) values" + string.Join(",", listSql);
    
                                cmd.CommandText = sql;
    
                                cmd.ExecuteNonQuery();
    
                                listSql.Clear();
    
                            }
    
                        }
    
                        if (listSql.Count > 0)
    
                        {
    
                            //处理残留的数据
    
                            string sql1 = "insert into t_users(UserName,Password) values" + string.Join(",", listSql);
    
                            cmd.CommandText = sql1;
    
                            cmd.ExecuteNonQuery();
    
                        }                   
    
                    }
    
                }
    
                sw.Stop();
    
                Console.WriteLine(sw.ElapsedMilliseconds);
    View Code
  • 相关阅读:
    spring boot 启动类 添加组件
    spirng boot 添加过滤器
    spring cloud spring-hystrix 缓存
    spring cloud spring-hystrix
    spring cloud spirng整合feign
    spring cloud feign
    cxf-client
    spring cloud客户端启用负载均衡
    spring cloud 负载均衡自定义
    VS2013 配置pthread
  • 原文地址:https://www.cnblogs.com/wangyinlon/p/6921808.html
Copyright © 2011-2022 走看看