C#下的winform编程相关知识

1、批量更新dataGridView表格时,提示:违反并发性操作原因:dbUpdate("select ID,Name,Pass,Dept,Mail from tb_Login", (DataTable)dataGridView1.DataSource)中前一个参数和dataGridView的数据源语句不一致。

注:用绑定数据源显示的dataGridView表格要清除行需要使用dataGridview.dataSource=null,不可以使用dataGridView.Rows.Clear(),否则会报错:不可以清除此列表。只有手动添加到表数据才可以使用清除函数Clear()。



2、不要把两个功能一样的事件同时声明而只用一个,容易造成双重操作,如:
SqlDataReader reader = MyClass.getcom("select * from material where 序列号='"+i.ToString()+"' "); //select x from [table] where [column] = Y
   if (reader.Read())  //手动遍历,否则无法SqlDataReader执行
   {
  int Value1 = reader.GetString(GetOrdinal("采购仓"));        //读取同一种原材料在采购仓和原料场中的数量(GetInt32()方法不灵活,其参数只能是int)
  int Value2 =reader.GetString(GetOrdinal("原料仓"));
  int Value = Value1 + Value2;

   }

注:上述GetString、GetOrdinal方法只可以读取数据表单元格不为NULL的对象,如果数据表单元格为空,会提示错误:数据为空。不能对 Null 值调用此方法或属性

此时可用如下方式读取:

(1)先判断是否为空:

if (!sdr.IsDBNull(9))

{

}

(2) 使用reader["MenuName"].ToString()读取,但该方法有缺陷,即只可以读取字符串,不过可以先读取为字符串然后转换类型;

reader.GetString(reader.GetOrdinal("MenuName"))和reader["MenuName"].ToString()的区别:
前者不能读取值为NULL的单元格,但可以读取各种类型数据,而后者则可以读取值为NULL的数据单元格,但只能读取string类型数据。


3、数据库操作中若给字段赋值为变量,那么变量也需要用单双引号引起来(还要加括号eg:('"+temp+"')),和字符串一样处理。
而立即数直接赋值即可。

4、reader.Read()对同一条记录存在性判断只能使用一次它本身(eg:if(reader.Read())),若要对同一条记录多次判断其存在性需要首次使用时就将其值读取出来。
解释:reader.Read()是遍历作用的函数。

5、对单元格输入类型的设置在重新绑定数据之后会失效,故每次重新绑定数据之后就需要在此设置单元格类型

6、DGV表格用代码直接赋值单元格不会引起自动产生新行,只有手动编辑最后一行时才会产生新行

7、dataGridView只能在未绑定数据源时才可以用代码添加行如:dataGridView2.Rows.Add()。

8、DataGridView绑定的数据表改变后,显示的字段顺序会和现在的数据表不一致。解决方法:改绑定前先将DataGridView数据源设为空null。

补充一个关于c#中DataGridView控件显示复选框的小技巧:如果需要DataGridView复选框列可以显示默认选中或不选中状态,可以不用添加dataGridViewCheckBoxColumn列,直接在普通的列上绑定布尔型数据源(数据表中相关列定义为布尔量)就可以显示出默认状态的复选框列。因为DataGridView普通单元格不能显示布尔型,只能以复选框形式展现出来。


9、SqlDataReader阅读器读取未完之前不要在其中加入其它Command语句,可能出现“阅读器关闭后尝试调用MetaData无效”,原因不详

11、close、dispose和application.exit的区别:

close关闭模式窗体时,对象仍然存在,调用Close函数释放资源后可能还需要再次使用(非模式窗体不适用)。

dispose,销毁对象,窗体对象被回收了,也就是不存在了,Dispose函数释放的资源不再使用。

application.exit.整个程序进程结束,项目中的所有对象都会被销毁,退出整个应用程序。


此处添加一个例子,关闭当前打开的窗体(除主界面以外),代码有两种形式如下:

for (int i = 0; i < Application.OpenForms.Count; i++)
                { 
                    Form f=Application.OpenForms[i];
                    if (f.Name != "F_main")
                    {
                        f.Close();
                    }
                }

foreach (Form f in Application.OpenForms)
                { 
                    if (f.Name != "F_main")
                    {
                        f.Close();
                    }
                }

分别采用了for循环和foreach遍历方式:如果所有的窗体都是模式窗体,那么两种方式都可行;一旦打开的窗体全部或部分为非模式窗体,那么遍历方式的就会报错:无法遍历,因为窗体集合已经修改。

原因:(1)模式窗体调用Close()函数后对象还不存在,需要调用Dispose()才会销毁,但非模式窗体调用Close()后就会自动调用Dispose()销毁窗体,即该窗体对象已不存在;

(2)遍历过程中枚举数组是不允许变化的,直到遍历结束。

结合以上两者:非模式窗体关闭后致使该窗体对象消失,也就造成了遍历枚举数组发生改变,所以报错。


12、问题:每次被迫重新登录后,原先打开的子窗体都会先使用close()函数在循环语句中关闭,然后在使用dispose()释放,但是在关闭后释放前那些子窗体中有部分控件或资源还会被引用,此时会不会引起异常?(暂时未发现)  备注:此处关系到软件的健壮性和可靠性

13、C#里面实现给数据库加锁解锁:
select * from table WITH(NOLOCK)
select * from table WITH(UPLOCK)
……
这些sql语句需要在command()中执行,括号的就是指示你的语句带什么锁。

锁的类型:
(1). 共享锁 SQL Server中,共享锁用于所有的只读数据操作。共享锁是非独占的,允许多个并发事务读取其锁定的资源。
(2). 更新锁 更新锁在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象。因为使用共享锁时,
修改数据的操作分为两步,首先获得一个共享锁,读取数据,然后将共享锁升级为排它锁,然后再执行修改操作。这样如果同时有两个或多
个事务同时对一个事务申请了共享锁,在修改数据的时候,这些事务都要将共享锁升级为排它锁。这时,这些事务都不会释放共享锁而是一
直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请更新锁,在数据修改的时候再升级为排它锁,就可以避免死锁。
(3).排它锁 排它锁是为修改数据而保留的。它所锁定的资源,其他事务不能读取也不能修改
(4).结构锁 执行表的数据定义语言 (DDL) 操作(例如添加列或除去表)时使用架构修改 (Sch-M) 锁。
(5).意向锁 意向锁说明SQL Server有在资源的低层获得共享锁或排它锁的意向。
(6).大容量更新锁 当将数据大容量复制到表,且指定了 TABLOCK 提示或者使用 sp_tableoption 设置了 table lock on bulk 表选项时,将
使用大容量更新 锁。大容量更新锁允许进程将数据并发地大容量复制到同一表,同时防止其它不进行大容量复制数据的进程访问该表。 

用sql语句表示锁:
  NOLOCK(不加锁) 
  此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到未完成事务(Uncommited Transaction)或
  回滚(Roll Back)中的数据, 即所谓的“脏数据”。 
  
  HOLDLOCK(保持锁) 
  此选项被选中时,SQL Server 会将此共享锁保持至整个事务结束,而不会在途中释放。 
  
  UPDLOCK(修改锁) 
  此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时
  读取数据但只有该进程能修改数据。 
  
  TABLOCK(表锁) 
  此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。 
  
  PAGLOCK(页锁) 
  此选项为默认选项, 当被选中时,SQL Server 使用共享页锁。 
  
  TABLOCKX(排它表锁) 
  此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。


  14、防止脏读:一般存在多用户对一个表进行操作的情况时,为了防止读到的是脏数据,每次提交前都要再次读取相关数据进行前后对照,看有无变化,若发现脏读就取消操作。

  15、一个项目下可以新建多个命名空间,调用某个命名空间外的类或者其他命名空间的类,需要使用引用文件.dll(补充:使用VS命令提示窗口生成dll文件的方法:Microsoft Visual Studio 2010-Visual Studio Tools-Visual Studio 命令提示(2010),然后先将源文件复制到命令窗口应用程序所在文件夹(该文件夹地址在输入光标前面有显示),然后用“csc/t:library 类文件名.cs”将其编译为.dll文件)。

  16、窗体之间交互的调用对方的数据或操作对方所属的控件一般可以使用:
  方式一:委托(适用于父子窗体之间交互操作,实现多线程工作或者说实现同步事件发生,比如:子窗体进行一个计算后,将
  结果用到主窗体的某个事件使得主窗体产生某种变化,且此方式不会加深窗体之间耦合加大);
  方式二:构造函数传值(会加深窗体之间的耦合且只能单向传值)
  方式三:直接在本窗体中实例化引用需要调用的窗体(会加深窗体之间的耦合)

  17、show()与showDialog(),模式窗体与非模式窗体

Show():Show()打开的是非模式窗口,在其打开一个窗体后还可以打开其他同级别或更高界别的窗体,关闭时也不需要人为的去调用Dispose()函数,因为这种模式下会自动调用。

ShowDialog():ShowDialog()打开的是模式窗口,在其打开一个窗体后就不可以打开或操作其他同级别或更高界别的窗体了(除非等到其关闭),关闭时也需要人为的去调用Dispose()函数,因为这种模式下不会自动调用Dispose()。


//非模式窗体 
From qform=new Form(); 
qform.Show(); 
//模式窗体 
Form qform=new Form(); 
qform.ShowDialog(); 

  18、sql读取语句的条件值为空,则应该如下写:select *from MenuRelation where MenuPID is null('='改为'is');

  19、数组创建:int []a = new int[20];或int[] array=new int[]{1,2,3,4};(常用的两种方式:不初始化和初始化的)
C#中新建(new)的数组未初始化时的初始值:string[]为null,int[]为0;
新建的数组需要指定容量,然后开辟连续存储区,不太适合大存储量数据存储;
若要大存储数组需用链表(包括结构体链表);

若数组大小不确定,也可以用List或Arraylist:List和Arraylist都是动态数组(List必须指定存储数据的类型),容量大小可改变,但存储区依然是连续的,这样就可能造成新添加的数据覆盖存储区已有数据。

C#中哈希表的使用:

(1)哈希表是存储以键/值对形式的数据结构,所以哈希表的每个元素都是由两部分组成‘键’和‘值’,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。

(2)Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对(如value可以是数组也可以是也可以是单个字符)。其中每个元素的key都有一个哈希函数用来根据key寻找值的存储地址,在C#中你的哈希表每添加一个元素都有一个默认的哈希函数与之对应,可以用key.GetHashCode()访问该函数,当然也可以自己重写哈希函数。

(3)哈希表最大的好处就是:查找速度快,因为每个元素只要知道键key就可以知道value所在的的存储地址区(桶),所以直接到相应的桶中查找即可,不需要顺序比较。

(4)我自己常用哈希表存储类似“描述/对应相关值”类型的数据,比如“物料名称/当前数量”这种需要对应存储的数据。


  20、使用VS自带的安装包生成setup.exe注意事项:要设置“从安装文件下载所需要的工具文件”。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值