让用户尽量少打字

每次让用户输入这么多信息的确很糟糕, 可以改进一下设计: 服务器IP和用户名可以存放在配置文件里面, 初始化的时候默认加载到相应的文本框中; 从安全角度考虑, 密码必须经过用户手动输入; 而数据库名字则没必要让用户输入, 有了服务器IP、用户名、密码后可以尝试连接SQL Server, 连接SQL Server成功后, 把数据库中所有的数据库名加载到ComboBox让用户选择连接哪个数据库.

密码不正确

密码正确

如何实现

在后台代码中定义一个计时器, 设置它的Interval为1000毫秒, 用户输入密码时让定时器重新计时, 也就是说用户输入密码后, 如果在1秒钟内用户没有继续输入密码, 则会触发计时器的Elapsed事件, 这时程序尝试能不能连上SQL Server.

1
2
3
4
5
6
7
8
9
10
11
//用户停止输入密码1秒后自动尝试连接
private System.Timers.Timer m_timer=new System.Timers.Timer(1000);
         
private void txtPassword_PasswordChanged(object sender, RoutedEventArgs e)
{
    m_timer.Stop();
    m_timer.Start();
 
    //清空数据库的选择列表
    cbbDatabase.Items.Clear();
}

在计时器的Elapsed事件函数中, 程序尝试连接SQL Server, 但是如下写法会出现问题.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    Dispatcher.BeginInvoke((Action)delegate()
    {
        var conStr = String.Format("Data Source={0};Integrated Security=False;User ID={1};Password={2};", txtServer.Text, txtUser.Text, txtPassword.Password);
        using (var con = new SqlConnection(conStr))
        {
            try
            {
                con.Open();
            }
            catch
            {
                //TODO: 提示连接数据库失败
                return;
            }
            //TODO:提示连接数据库成功
 
            var sql = "select name from sys.databases";
            var cmd = new SqlCommand(sql, con);
            IAsyncResult asyncResult = cmd.BeginExecuteReader();
            SqlDataReader reader = cmd.EndExecuteReader(asyncResult);
            if (!reader.HasRows)
            {
                //TODO: 提示SQL Server中不存在数据库
                return;
            }
            //TODO: 在这里释放Timer
 
            while (reader.Read())
            {
                cbbDatabase.Items.Add(reader[0].ToString());
            }
        }
    });
}

如果数据库的IP是错误的, con.Open()则要花费约30秒左右才会抛出异常, 这段时间UI线程会一直卡死, 经过测试, 30秒后才抛异常与数据库连接字符串的Connect Timeout属性没有关系.

可以写一个SqlConnection的扩展方法, 在这个方法里面用一个码表对执行con.Open()的时间计时, 用一个bool型变量标识有没有成功的con.Open(), 如果在规定的时间内没有成功连上SQL Server则抛出一个异常.

扩展SqlConnection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public static class SqlExtension
{
    public static void TryOpen(this SqlConnection connection, int millisecondTimeout)
    {
        Stopwatch sw = new Stopwatch();
        bool succeed = false;
 
        Thread t = new Thread(() =>
            {
                try
                {
                    sw.Start();
                    connection.Open();
                    //打开连接后设置succeed为true
                    succeed = true;
                }
                catch
                {
                }
            });
        t.IsBackground = true;
        t.Start();
        t.Join(millisecondTimeout);
        t.Abort();
 
        //如果没有成功, 则抛出一个异常
        if (!succeed)
            throw new Exception();
    }
}

这样在原来的代码中调用con.TryOpen()就可以解决问题.

扩展delegate

其实扩展方法的第一个参数并不是一定要是一个class类, 其实delegate也是可以的, delegate其实在编译之后就是一个类, 如下改写刚刚的SqlConnection扩展方法, 就可以写一个通用的尝试操作的扩展方法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static class ActionExtension
{
    public static void Invoke(this Action action, int millisecondTimeout)
    {
        Stopwatch sw = new Stopwatch();
        bool succeed = false;
 
        Thread t = new Thread(() =>
            {
                try
                {
                    sw.Start();
                    action();
                    succeed = true;
                }
                catch
                {
                }
            });
        t.IsBackground = true;
        t.Start();
        t.Join(millisecondTimeout);
 
        if (!succeed)
            throw new Exception();
    }
}

这样写, 代码则更为通用一些, 以后一些耗时的操作(当然要满足Action的签名)都可以调用这个方法, 在本例中, 可以如下调用:

1
((Action)con.Open).Invoke(2000);

对delegate进行扩展 打造通用的"计时完成"方法 z的更多相关文章

  1. RBAC打造通用WEB权限

    RBAC不用给用户单个分配权限,只用指向对应的角色就会有对应的权限,而且分配权限和收回权限都很方便 5个关系对应5张表 五张表设计 CREATE TABLE `user` ( `id` ) unsig ...

  2. 为RecyclerView打造通用Adapter

    ##RecycleView简单介绍 RecyclerView控件和ListView的原理有非常多相似的地方,都是维护少量的View来进行显示大量的数据.只是RecyclerView控件比ListVie ...

  3. Android教你怎样一步步打造通用适配器

    前言 在Android开发中ListView是最为经常使用的控件之中的一个,基本每一个应用都会涉及到它,要使用ListView列表展示,就不可避免地涉及到另外一个东西--Adapter,我们都知道,A ...

  4. 为RecyclerView打造通用Adapter 让RecyclerView更加好用

    原文出处: 张鸿洋 (Granker,@鸿洋_ ) 一.概述 记得好久以前针对ListView类控件写过一篇打造万能的ListView GridView 适配器,如今RecyclerView异军突起, ...

  5. 转载扩展Windows Mobile模拟器存储空间的方法

    扩展Windows Mobile模拟器存储空间的方法 在Windows Mobile应用程序开发的初期,可以使用SDK自带的模拟器来进行调试,这给我们开发人员提供了一种方便的途径.一般的应用程序,占用 ...

  6. delphi附带通用控件安装方法:

    附带通用控件安装方法:----------基本安装1.对于单个控件,Componet-->install component..-->PAS或DCU文件-->install;2.对于 ...

  7. 通用Mapper的各个方法描述,参考官方

    下面是通用Mapper的各个方法描述,主要还是看官方的描述https://mapperhelper.github.io/all/. 基础接口 Select 接口:SelectMapper<T&g ...

  8. 关于visual studio code在win10系统上安装后会报扩展宿主意外终止的解决方法

    我的电脑的地址 C:\Users\Administrator.SC-201810160958\AppData\Local\Programs\Microsoft VS Code\resources\ap ...

  9. jQuery通用的全局遍历方法$.each()用法实例

    1.jQuery通用的全局遍历方法$.each()用法 2. test.json文件代码: 3. html代码 4.jQuery代码 <script src="jquery-1.3.1 ...

随机推荐

  1. POJ 1906

    #include <iostream> #include <string> #define MAXN 150 using namespace std; int _m[MAXN] ...

  2. REST_FRAMEWORK加深记忆-第二次练习官方文档

    我想,其它几个基于PYTHON的REST API模块概念都差不多吧. 先深入搞定这个吧. 前几次练习完了有一些印象,并且在工作中实践过一个,现在多弄几次,玩熟悉点. Serializers.py __ ...

  3. [hackerrank]The Love-Letter Mystery

    https://www.hackerrank.com/contests/w3/challenges/the-love-letter-mystery 简单题. #include <cstdlib& ...

  4. SpringMVC学习总结(六)——SpringMVC文件上传例子(2)

    基本的SpringMVC的搭建在我的上一篇文章里已经写过了,这篇文章主要说明一下使用SpringMVC进行表单上的文件上传以及多个文件同时上传的不同方法 一.配置文件: SpringMVC 用的是 的 ...

  5. ArcEngine查询、添加、删除要数的方法

    原文地址:http://www.cnblogs.com/caodajieup/archive/2011/11/02/2232658.html 1.查找数据 1).利用FeaturCursor进行空间查 ...

  6. 10、JPA_映射双向多对多的关联关系

    双向多对多的关联关系 双向多对多的关联关系(抽象成A-B)具体体现:A中有B的集合的引用,同时B中也有对A的集合的引用.A.B两个实体对应的数据表靠一张中间表来建立连接关系. 同时我们还知道,双向多对 ...

  7. .net 生成拼音码与五笔码

    首先加入配置文件: <?xml version="1.0" encoding="utf-8" ?> <CodeConfig> <S ...

  8. Ubuntu安装Apache

    在虚拟机上安装了Ubuntu13.10 ,然后使用命令 sudo apt-get install apache2 安装apache总提示“E: 未找到软件包...”,不知所踪,这可能是新手容易的犯 的 ...

  9. 【C#设计模式——创建型模式】简单工场模式

    进入码农行列也有一年半载了,仍然感觉自己混混沌沌,无所事事,无所作为,,,想想都下气,下气归下气,仍要奋起潜行,像愤怒的小鸟一边又一遍的冲向猪头也好,像蜗牛一样往前蹭也罢,总之要有蚂蚁啃骨头的精神!! ...

  10. Android L 使用ART能提高多少性能?

    点击打开链接 刚刚结束的 Google I/O 大会上,Android 下一代操作系统「L」带来不少惊喜.新系统运行更快.更省电. 然而开发者对这个新系统也有颇多疑问,比如新的运行模式 ART 对开发 ...