最近被winform里的datagridview ADO.NET的dataset dataadapter以及跨表弄得蛋疼不行,解决方法就是换方法!

你要是使用datagridview然后看重他的绑定数据方便,然后还提供更新数据库啥的就用了。。那遇到问题。你会变得很蛋疼。。最近用这个东西我觉得我把BAIDU GOOGLE关于datagridview 多表 Concurrency violation(这个万恶的错误!) 外键 更新这些关键字搜出来的前4-5页全看了~结果还是没办法。。。弄得我这个周末都难过。。所以我决定 换个方式。。

其实最主要的问题就是想用用datadapter的自动update功能。。毕竟人家是微软做的么,效率肯定比自己写的要高吧~而且调人家一句UPDATE就能更新你一张表~多NB~结果呢。。恩 各种错误~恩。要总结错误~毕竟花了那么多时间~

1.datagridview

这个东西吧~有好多属性其实自己一点都不知道的。。然后就不知道咋用。。

datagridview绑定数据流程其实很简单,一个datasource=dataset就行,当然,用个bindingsource也行,因为我还有个navigator和datagridview绑定同样的东西,所以我用了个bingdingsource

当然这样绑定出来的东西也不好看~设置columns的各种属性,其中单个列直接用column【“列名”】来引用就行,hedatext、readonly之类的随便用~

 DataTable dt = DataAccess.dataTable("select NAME,LEAF.ID AS ID,TYPE,WEIGHT FROM MAINSTRUCTURE,LEAF WHERE MAINSTRUCTURE.ID=LEAF.ID"); 

            BindingSource bind = new BindingSource();

            bind.DataSource = dt;

            this.dataGridview1.DataSource = bind ;

           this.bindingNavigator1.BindingSource = bind;

 

           this.dataGridview1.Columns["NAME"].HeaderText = "叶节点名称";

           this.dataGridview1.Columns["NAME"].ReadOnly = true;

           this.dataGridview1.Columns["ID"].Visible = false;         

           this.dataGridview1.Columns["TYPE"].HeaderText = "类型";

           this.dataGridview1.Columns["WEIGHT"].HeaderText = "权值";

datacomboboxcolumn这个东西说是能实现combobox效果。。但是我没用~用的是网上一个更好的东西~他让combobox列表面上看起来像个textbox列,但是用的时候是combobox效果~非常实用

combox cmbLeafType = new combox  //这是一个简单的combox 在使用单个单元格的时候使用    

this.cmboLeafType.Visible = false;

cmboLeafType.SelectedIndexChanged += new EventHandler(cmboLeafType_SelectedIndexChanged);

this.dataGridview1.Controls.Add(cmboLeafType);

 

//下拉菜单改变后改变datagridview中的内容

        private void cmboLeafType_SelectedIndexChanged(object sender, System.EventArgs e)

        {

            if (((ComboBox)sender).Text == "成本型")

            {

 

                 dataGridview1.CurrentCell.Value = "成本型";

            }

            else if (((ComboBox)sender).Text == "效益型")

            {

                dataGridview1.CurrentCell.Value = "效益型";

            }

            else

            {

                dataGridview1.CurrentCell.Value = "固定型";

            }

 

        }

 

 //单击类型单元格时触发

        private void dataGridview1_CurrentCellChanged(object sender, EventArgs e)

        {

            try

            {

                if (this.dataGridview1.CurrentCell.ColumnIndex == 2) //这里因为combox列在第三列

                {

                    Rectangle rect = dataGridview1.GetCellDisplayRectangle(dataGridview1.CurrentCell.ColumnIndex, dataGridview1.CurrentCell.RowIndex, false);

 

                        cmboLeafType.Text = dataGridview1.CurrentCell.Value.ToString();

 

                    cmboLeafType.Left = rect.Left;

                    cmboLeafType.Top = rect.Top;

                    cmboLeafType.Width = rect.Width;

                    cmboLeafType.Height = rect.Height;

                    cmboLeafType.Visible = true;

                }

                else

                {

                    cmboLeafType.Visible = false;

                }

            }

            catch

            {

            }

        }

2.用datatable保存至数据库

这个东西最头大了。。。其实ADO.NET中用datadapter 和commandbuilder可以无脑操作数据库单表。。当有跨表的选择 这个commandbuilder就2了,而且数据层的API不是我做的,同学竟然每次都要先用OPEN函数获得CONNECTION 和 COMMAND,再生成adapter,完了之后销毁。。这使我每次用adapter都是新建的。。每一个完整的。。这样更新起来也很麻烦。。先说怎么用吧~

简单的用adapter更新就是先获取

datadapter da = new datapter(conn);

adapter.fill(ds) //获得搜索的DS

然后在更新函数中用

commandbuilder cb = new commandbuilder(da); //这里commandbuilder用DA做参数生成各种SQL语句~

接着直接使用

da.update(ds);

就可以更新数据库数据与ds一样。。

以上都是单表以及无并发情况下的无脑使用。一旦遇到跨表更新之类的就恶心了。。

当然 数据库有个很好的功能叫存储过程~调用这个可以直接对任意表实现批量更新,但是当你用的数据库不支持这个你就郁闷了。。看得到摸不着啊。。。

当然.NET也想到了这个。。于是乎 人家也模拟存储过程,用自己的command让用户自己写UPDATE更新信息,反正看上去是很好用~

string sql = "update LEAFVIEW set TYPE=@TYPE,WEIGHT=@WEIGHT where ID=@ID";

            OleDbDataAdapter da = new OleDbDataAdapter();

            try

            {

                openConnection(); //这就是那个同学每次要打开数据库获得connection以及command的函数。。。

                comm.CommandText = sql;

                //配更新用的Command               

                OleDbParameter sp = new OleDbParameter();

                sp = comm.Parameters.Add("@ID", OleDbType.WChar, 30);

                sp.SourceColumn = "ID"; //源数据列

                sp.SourceVersion = DataRowVersion.Original;

 

                sp = comm.Parameters.Add("@TYPE", OleDbType.WChar, 30);

                sp.SourceColumn = "TYPE";

                sp.SourceVersion = DataRowVersion.Current;

 

                sp = comm.Parameters.Add("@WEIGHT", OleDbType.Double);

                sp.SourceColumn = "WEIGHT";

                sp.SourceVersion = DataRowVersion.Current;

 

      //把配好的cmd赋给da.UpdateCommand

                da.UpdateCommand = comm;

 

                  da.Update(dt);

 

            }

以上看上去天衣无缝~但是反正不知道为什么就是更新不成功,难道是我DT里面有个非LEAF表的列?反正以后就是无尽的concurrency violation错误。。这个错误是人家ADO.NET内部抛出的,我找死了也找不出原因,有说是要用datagridview.endinit()方法的,有的说是数据库中数据已经改掉了~dataset里面的数据不是最新的也不是最旧的具体解释参考http://msdn.microsoft.com/zh-cn/magazine/cc163924(en-us).aspx

其他concurrency violation错误参考 http://www.yesky.com/468/1771468_4.shtml

http://book.csdn.net/bookfiles/73/100732091.shtml

 

这篇文章对级联更新帮助蛮大~我很大一部分是参考这篇的。。

http://www.cnblogs.com/jason-xiao/archive/2009/11/29/1613326.html

多表更新。。说实话 没太看懂,而且问题跟我的不大同 于是也没仔细看~

http://blog.csdn.net/zhzuo/archive/2004/08/06/67016.aspx

http://blog.csdn.net/zhzuo/archive/2004/08/06/67037.aspx

http://blog.csdn.net/zhzuo/archive/2005/01/03/238273.aspx

OK学习就这么多~网页总算清净了~改代码去。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值