啦啦啦,啦啦啦,偶的点要开啦

西湖美景三月天,春雨如酒柳如烟

 

从数据库中读取空值的处理

 

DBNull.Value对数据库,为null值
null对对象,为空

该类用于指示不存在某个已知值(通常在数据库应用程序中)。

在数据库应用程序中,空对象是字段的有效值。该类区分空值(空对象)和未初始化值(DBNull.Value 实例)。例如,表可以包含具有未初始化字段的记录。默认情况下,这些未初始化字段具有 DBNull 值。


string sConnectionString = @"data source=.;initial catalog=UserFilesSonBrother;" +
"Integrated Security=True";
SqlConnection conn = new SqlConnection(sConnectionString);
SqlDataAdapter sda = new SqlDataAdapter("select * from tblUserFilesTest",
conn);
dsUserFiles = new DataSet();
sda.Fill(dsUserFiles);

AddTree(null,1);

private void AddTree(TreeNode pNode, int SID)
{
DataView dvTree = new DataView (dsUserFiles.Tables[0]);
dvTree.RowFilter = "[ID]=" + SID.ToString();
if (dvTree.Count == 0)
return;
do
{
DataRowView drvBranch = dvTree[0];
TreeNode Child=new TreeNode ();
Child .Text =drvBranch ["Name"].ToString ();
Child .Value =drvBranch ["ID"].ToString ();
if (pNode ==null)
tvUserFilesTreeView .Nodes .Add (Child );
else
pNode .ChildNodes .Add (Child );
Child .Expanded =true;
if ( drvBranch["SID"]!=DBNull .Value )
AddTree (Child ,int.Parse ( drvBranch ["SID"].ToString ()));
if (drvBranch ["BID"]== DBNull.Value )
return ;
int BrotherID=int.Parse ( drvBranch ["BID"].ToString ());
dvTree.RowFilter = "[ID]=" + BrotherID.ToString();
}while (dvTree .Count !=0);

}


这是一段从数据库中读取到空值的例子,原来用drvBranch["SID"]!=null判断会出错,即使这时该字段是空值,但程序认为它并不等于null。

除了空值,其他的数据库返回值都是object,使用前要做转换。

 

 

----------------------------------------------------------------------------------------------

关于DataView

CSDN有人这么说:“视图只是一组基于基本表的数据集,说穿了,数据库中没有他的实际存储,而只是保存了他的定义而已。”

MSDN的:DataView 使您能够创建 DataTable 中所存储的数据的不同视图,这种功能通常用于数据绑定应用程序。使用 DataView,您可以使用不同排序顺序显示表中的数据,并且可以按行状态或基于筛选器表达式来筛选数据。
DataView 提供基础 DataTable 中的数据的动态视图:内容、排序和成员关系会实时反映其更改。此行为不同于 DataTable 的 Select 方法,后者从表中按特定的筛选器和/或排序顺序返回 DataRow 数组,虽然其内容反映对基础表的更改,但其成员关系和排序却则保持静态。DataView 的动态功能使其成为数据绑定应用程序的理想选择。
 
 
-----------------------------------------------------------------------------------------------
 

父亲树和儿子兄弟树遍历的速度比较

配置:P42.5G,1G内存,XP SP3系统,在本机用ASP.NET环境
父亲树:

DataSet dsUserFiles;
int Counts;

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string sConnectionString = @"data source=.;initial catalog=UserFilesSonBrother;" +
"Integrated Security=True";
SqlConnection conn = new SqlConnection(sConnectionString);
SqlDataAdapter sda = new SqlDataAdapter("select * from tblUserFiles",
conn);
dsUserFiles = new DataSet();
sda.Fill(dsUserFiles);

Stopwatch swTime = new Stopwatch();
swTime.Start();

for (int i = 0; i < 100; i++)
{
Counts = 0;
AddTree(0, (TreeNode)null);
tvUserFilesTreeView.Nodes.Clear();
}
int time = (int)swTime.ElapsedMilliseconds;
long ticks = swTime.ElapsedTicks;
Response.Write("填充树100次耗费时间:" + time + "(毫秒)<br>");
Response.Write("耗费计数器刻度:" + ticks + "次<br>");
Response.Write("每次调用递归函数的次数:" + Counts + "次<br>");

}

}

private void AddTree(int ParentID, TreeNode pNode)
{

Counts++;
DataView dvTree = new DataView(dsUserFiles.Tables[0]);
dvTree.RowFilter = " [PID]= " + ParentID;

foreach (DataRowView Row in dvTree)
{
TreeNode Node = new TreeNode();
if (pNode == null)
{
Node.Text = Row["Name"].ToString();
tvUserFilesTreeView.Nodes.Add(Node);
Node.Expanded = false ;
AddTree(Int32.Parse ( Row["ID"].ToString ()), Node);
}
else
{
Node.Text = Row["Name"].ToString();
pNode.ChildNodes.Add(Node);
Node.Expanded = true;
AddTree(Int32.Parse(Row["ID"].ToString()), Node);
}
}
}


结果:
填充树100次耗费时间:21599(毫秒)
耗费计数器刻度:77316704次
每次调用递归函数的次数:170次

儿子兄弟树:

int Counts;
DataSet dsUserFiles;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string sConnectionString = @"data source=.;initial catalog=UserFilesSonBrother;" +
"Integrated Security=True";
SqlConnection conn = new SqlConnection(sConnectionString);
SqlDataAdapter sda = new SqlDataAdapter("select * from tblUserFilesTest",
conn);
dsUserFiles = new DataSet();
sda.Fill(dsUserFiles);
DataView dvRoot = new DataView(dsUserFiles.Tables[0]);
dvRoot.RowFilter = "[ID]=0";

Stopwatch swTime = new Stopwatch();
swTime.Start();

for (int i = 0; i < 100; i++)
{
Counts = 0;
AddTree(null,int.Parse(dvRoot [0]["SID"].ToString ()));
tvUserFilesTreeView.Nodes.Clear();
}
int time = (int)swTime.ElapsedMilliseconds;
long ticks = swTime.ElapsedTicks;
Response.Write("填充树100次耗费时间:" + time + "(毫秒)<br>");
Response.Write("耗费计数器刻度:" + ticks + "次<br>");
Response.Write("每次进入递归调用的次数:" + Counts + "次<br>");

}

}

private void AddTree(TreeNode pNode, int SID)
{
Counts++;
DataView dvTree = new DataView (dsUserFiles.Tables[0]);
dvTree.RowFilter = "[ID]=" + SID.ToString();
if (dvTree.Count == 0)
return;
do
{
DataRowView drvBranch = dvTree[0];
TreeNode Child=new TreeNode ();
Child.Text = drvBranch["Name"].ToString ();
Child .Value =drvBranch ["ID"].ToString ();
if (pNode ==null)
tvUserFilesTreeView .Nodes .Add (Child );
else
pNode .ChildNodes .Add (Child );
Child .Expanded =true;
if ( drvBranch["SID"]!=DBNull .Value )
AddTree (Child ,int.Parse ( drvBranch ["SID"].ToString ()));
if (drvBranch ["BID"]== DBNull.Value )
return ;
int BrotherID=int.Parse ( drvBranch ["BID"].ToString ());
dvTree.RowFilter = "[ID]=" + BrotherID.ToString();
}while (dvTree .Count !=0);

}



结果:
填充树100次耗费时间:8989(毫秒)
耗费计数器刻度:32177437次
每次进入递归调用的次数:47次

儿子兄弟结构的优势很明显,因为父亲树对不论树枝还是叶子都要进入递归一次,而儿子兄弟树只要进树枝,叶子不进。(好像是因为这样子。。。。。。
 
 
----------------------------------------------------------------------------------------------
 

消息响应函数的参数类型

比如:
protected void tvUserFilesTreeView_SelectedNodeChanged(object sender, EventArgs e)
两个参数都是默认类型的,现在知道sender其实是TreeView类的,那么可以这样引用它:
TreeView tvBuf = sender as TreeView;
Response.Write("你选择了:"+tvBuf .SelectedNode.Text +"节点");

也可以:
TreeView tvBuf = (TreeView)sender;
关于这两种方法的区别,CSDN有人说:
用as,转换不成功的时候结果是null,所以很容易判断转换是否成功。
不仅仅是抛异常或转换不成功返回null那么简单...as运算符只可用于引用类型,所以对值类型的强制转换无能为力...
 
 
------------------------------------------------------------------------------------------------
 

在页面动态添加控件

比如直接加在Page中:
如果直接使用
Page.Controls.Add(btTest);
会出错:类型“Button”的控件“ctl04”必须放在具有 runat=server 的窗体标记内。
原因:估计是直接加在Page的第一个窗体标记,也就是html后面了啦啦啦,啦啦啦,偶的点要开啦啦啦啦,啦啦啦,偶的点要开啦
应该这样:
Page.Controls[3].Controls.AddAt(0,btTest);
就是加到form1标记中第一个位置了。

运行:
int i=0;
foreach (Control ctlLook in Page.Controls)
{
Response.Write("页面控件" + i + ":" + ctlLook.ID + "<br>");
i++;
}


可以看到:

页面控件0:
页面控件1:
页面控件2:
页面控件3:form1
页面控件4:

当然,还可以使用容器控件来精确的定位。
 
 
---------------------------------------------------------------------------------------------
 

动态添加的控件的响应问题

先做个试验:

<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /></div>
</form>


protected void Page_Load(object sender, EventArgs e)
{
int x = 321; //设置中断
}
protected void Button1_Click(object sender, EventArgs e)
{
int i = 123; //设置中断
}


点击按钮后先重载页面(进入Page_Load),然后才到响应。

所以,动态添加的控件,如果没有在重载时重新装入,是不会响应消息的,因为那时控件已经没有了。
CSDN:动态添加控件要在page_load事件中或在此事件之前增加,并增加事件挂钩.
要是在用户事件中增加控件要在postback后在page_load时间前重新载入你的控件
如果你的获取是说页面PostBack之后,你需要创建同样一个控件,添加到同样的地方,设置同样的ID,以确保ClientID一致,这样就能把值读出来了。

DataSet dsUserFiles;
protected void Page_Load(object sender, EventArgs e)
{
string sConnectionString = @"data source=.;initial catalog=UserFilesSonBrother;" +
"Integrated Security=True";
SqlConnection conn = new SqlConnection(sConnectionString);
SqlDataAdapter sda = new SqlDataAdapter("select * from tblUserFilesTest",
conn);
dsUserFiles = new DataSet();
sda.Fill(dsUserFiles);
DataView dvRoot = new DataView(dsUserFiles.Tables[0]);
dvRoot.RowFilter = "[ID]=0";
if (dvRoot .Count !=0)
AddTree(null,int.Parse(dvRoot [0]["SID"].ToString ()));
if ((string )ViewState["IsNodeSelected"] == "true")
{
TextBox tbName = new TextBox();
tbName.Text = "请输入新节点名称";
tbName.ID = "tbNAME";

Button btAdd = new Button();
btAdd.Text = "增加节点";
btAdd.ID = "btADD";

btAdd.Click += new EventHandler(btAdd_Click);

Page.Form.Controls.AddAt(0, tbName);
Page.Form.Controls.AddAt(1, btAdd);

}

}

private void AddTree(TreeNode pNode, int SID)
{
DataView dvTree = new DataView (dsUserFiles.Tables[0]);
dvTree.RowFilter = "[ID]=" + SID.ToString();
if (dvTree.Count == 0)
return;
do
{
DataRowView drvBranch = dvTree[0];
TreeNode Child=new TreeNode ();
Child.Text = drvBranch["Name"].ToString ();
Child .Value =drvBranch ["ID"].ToString ();
if (pNode ==null)
tvUserFilesTreeView .Nodes .Add (Child );
else
pNode .ChildNodes .Add (Child );
Child .Expanded =true;
if ( drvBranch["SID"]!=DBNull .Value )
AddTree (Child ,int.Parse ( drvBranch ["SID"].ToString ()));
if (drvBranch ["BID"]== DBNull.Value )
return ;
int BrotherID=int.Parse ( drvBranch ["BID"].ToString ());
dvTree.RowFilter = "[ID]=" + BrotherID.ToString();
}while (dvTree .Count !=0);

}

protected void tvUserFilesTreeView_SelectedNodeChanged(object sender, EventArgs e)
{
// TreeView tvBuf = sender as TreeView;
TreeView tvBuf = (TreeView)sender;
Response.Write("你选择了:"+tvBuf .SelectedNode.Text +"节点<br>");

TextBox tbName=new TextBox ();
tbName.Text = "请输入新节点名称";
tbName.ID = "tbNAME";
Button btAdd=new Button ();
btAdd.Text = "增加节点";
btAdd.ID = "btADD";

btAdd.Click += new EventHandler(btAdd_Click);

Page.Form.Controls.AddAt(0, tbName);
Page.Form.Controls.AddAt(1, btAdd);

ViewState["NodeSelectedID"] = tvBuf.SelectedNode.Value;
ViewState["IsNodeSelected"] = "true";

// Page.Controls.Add(btTest);
}

void btAdd_Click(object sender,EventArgs e)
{
Response .Write ("<script>alert('您点击了我')</script>");
}



有点麻烦哦
 
 
---------------------------------------------------------------------------------------------
 

动态添加的控件的移除问题

Page .Form .Controls .Remove (Control Value);不会用,控件对象名称或者ID代入都不对。
Page.Form.Controls.RemoveAt(int index);只好用这个,有个地方要注意的是,每次移除一个控件之后,容器会发生变化,控件的索引也相应改变,举例如下:
Page.Form.Controls.RemoveAt(0);
Page.Form.Controls.RemoveAt(1);

这样移除的是0,1两个控件吗?NO~是原来的0,2这两个控件。应该这样:
Page.Form.Controls.RemoveAt(0);
Page.Form.Controls.RemoveAt(0);


CSDN有帖子说的很好:

问:
昨天在做一个WINDOWS程序时,需要动态释放掉几个名称以lbl开头的标签.
代码如下:
foreach (Control con in Controls)
{
if (con.GetType().Name == "Label")
{
Label lbl = (Label)con;
if (lbl.Name.Substring(0, 3) == "lbl")
{
Controls.Remove(lbl);
lbl.Dispose();
lbl = null;
}
}
}

这样做了后界面上是清除掉了标签,但程序偶尔会出现清理不干净的情况
后来经过调试排查,发现Controls里有12个控件,有5个标签,4个以lbl开头,但是只清理掉了其中的2个,还有2个没有被遍历到.
虽然没遍历到,但界面上却又找不到这两个控件了.不知道是为什么.
请教各位前辈~~~

答:
这很正常,原因是你在清除是Controls容器大小发生了变化。
正确的清除方法应当是这样:

C# code public void DoClear()
{
ArrayList list = new ArrayList();
foreach (Control con in Controls)
{
// 这样保留了要移除的控件,同时不让Controls容器中的元素发生变化,
// 如果发生变化,程度将变得很异常。
if (con is Label)
{
list.Add(con);
}
}
foreach (Control ctrl in list)
{
Controls.Remove(ctrl);
//这里你也不需要执行ctrl.Dispose()
}
}

问:
呵呵...问题解决了
正像beginCsdn所说的
不过我还不是很理解,请问具体是我的哪一步触动了Controls的变化呢

答:
因为controls是个容器,你使用它的remove方法,结果count大小会发生变化,而foreach的结果将不能取得正确的IEnumerator,即内部序号已经发生变化,而外部遍历仍然使用原有序号去遍历的话,结果就不多说了,这是一次性删除某个容器中多个数据的技巧。不单单是这种情况下会用的,有许多许多的地方会用到,如一次性从树中删除多个结点等。
 
 
----------------------------------------------------------------------------------------------
 

C#中的随机数

因为C#中的随机数是伪的,需要提供变化的种子才能实现真正的随机。

CSDN:

想用c# 生成一组随机密码,可出现这样的情况:
一组50个随机密码里,前10个一样,然后后12个一样,然后又9个一样的
如果在生成密码的前边加个中断,按F10运行下去,结果就是一组中没有一个重复的...

原码如下,求高人帮忙:

private void button1_Click(object sender, EventArgs e)
{
label1.Text = "";
string RomPass = "";
string a1 = "";
for (int i = 0; i < 10; i++)
{
RomPass = GetCharFont(18);
a1 += RomPass + "\r";
}
label1.Text = a1;
}

//得到数字加英文的随机数,参数:随机数长度,返回值:一个字符串!"
public string GetCharFont(int strLength)
{
char[] constant = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
System.Text.StringBuilder newRandom = new System.Text.StringBuilder(62);
Random rd = new Random();
for (int i = 0; i < strLength; i++)
{
newRandom.Append(constant[rd.Next(62)]);
}
return newRandom.ToString();
}


点击按钮执行结果:
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ
MfL8kCgpCnn82DeHsJ

解决思路: 在Random时,系统默认好像是以时间为基础产生随机数值,那当调用Random过快时,每次的时间值一至的时候,产生的结果将是一至的!
那这个时候将Random的基础改为一个一定变化的量,才能使结果产生变化。
当然我们在重复、短时间内调用Random的话,一定会用到For 那么将For的循环值继承到Random基础值中,那么产生的结果就一定不同!
Random rd = new Random(Convert.ToInt32((DateTime.Now.Ticks + Rom) % Int32.MaxValue));
 
 
---------------------------------------------------------------------------------------------
 

关于动态创建gridview的模板列

MSDN有高手是这样说:
可以发现运行时创建GridView 模板列是很繁琐的事情,因此没有特殊需求,应该使用页面声明方式,动态解析构造Template 这些繁琐易错的 事情交由ASP.NET 解析器完成。
运行时动态任何服务器控件,必须确保每次请求/ 回发时,动态创建控件代码都能运行,典型错误是将这些放在一个Button_Click 中,当其他 PostBack 的时候,这些控件将会丢失。
代码技巧:匿名方法与 as 关键字的使用(C# 中类型转换)
很多朋友想通过动态创建列,来按需加载目标列,想法是好的,但鉴于ASP.NET 原理特别是生命周期与ViewState 的特殊性,这是易错又吃 力不讨好的苦差事。
个人建议是使用:

o 假如DataSource 是DataTable/DataView (或者DTO ),使其包含只需要的Column ,设置GridView.AutoGenerateColumns=true ,由GridView 内部在运行时自动反射创建列。

o 以声明方式声明全部所需的Column ,运行时调整GridView.Columns[index].Visible 来控制列的可见性。
 
 
-------------------------------------------------------------------------------------------
 

调整gridview中列的位置

可以通过gridview.insert()和gridview.remove()方法,来间接的调整列位置,因为没有直接调整的方法。
    protected void gvCurrentLevelFiles_DataBinding(object sender, EventArgs e)
    {
        gvCurrentLevelFiles.Columns.Insert(3, gvCurrentLevelFiles.Columns[0]);
        gvCurrentLevelFiles.Columns.RemoveAt(0);
    }
 
 
--------------------------------------------------------------------------------------------
 

关于<%# %>

MSDN:
所有数据绑定表达式都必须包含在 <%# 和 %> 字符之间。
ASP.NET 支持分层数据绑定模型,该模型创建服务器控件属性和数据源之间的绑定。几乎任何服务器控件属性都可以绑定到任何公共字段或属性,这些公共字段或属性位于包含页或服务器控件的直接命名容器上。
数据绑定表达式使用 Eval 和 Bind 方法将数据绑定到控件,并将更改提交回数据库。Eval 方法是静态(只读)方法,该方法采用数据字段的值作为参数并将其作为字符串返回。Bind 方法支持读/写功能,可以检索数据绑定控件的值并将任何更改提交回数据库。

貌似它不能嵌套,就是<%# ...<%#...%>...%>是不行的,但是对于复杂的格式,我们可以用函数来实现:
页面文件:
                        <asp:TemplateField HeaderText="类型试验">
                            <ItemTemplate >
                                <%# TypeDetail(eval_r("Type").ToString ())  %>
                            </ItemTemplate>
                        </asp:TemplateField>
代码文件:
    public string TypeDetail(string strType)
    {
        if (strType == "文件")
            return "文件";
        else
            return "这是"+strType+"目录";
    }
 
 
------------------------------------------------------------------------------------------
 

using() 模块

using 执行完后会自动调用 Dispose()方法,所以在using{}模块之后再次打开数据库连接,就要重新为conn的ConnectionString赋值:

string strBuf;
string strConnectionString = @"Data Source=.;Initial Catalog=dbUserFilesInfoBases;" +
" User ID=sa;Password=123456";
SqlConnection conn = new SqlConnection(strConnectionString);
string strSelectCommand = "select SID from tblTestUserFilesTree where ID = " +
PID.ToString();
SqlCommand cmd = new SqlCommand(strSelectCommand, conn);
using (conn)
{
conn.Open();
strBuf = cmd.ExecuteScalar().ToString();
}
if (strBuf == "")
{
string strInsertCommand="insert into tblTestUserFilesTree (Name,IsFolder,PID) "+
" values ('"+strFileName+"','false',"+PID.ToString ()+")";
strSelectCommand = "SELECT TOP (1) ID FROM tblTestUserFilesTree ORDER BY ID DESC";
conn.ConnectionString = strConnectionString;
using (conn)
{
conn.Open();
cmd = new SqlCommand(strInsertCommand, conn);
cmd.ExecuteNonQuery();
cmd.CommandText = strSelectCommand;
MyID = int.Parse(cmd.ExecuteScalar().ToString());
string strUpdateCommand ="update tblTestUserFilesTree set "+
" SID="+MyID +" where ID="+PID.ToString () ;
cmd.CommandText = strUpdateCommand;
cmd.ExecuteNonQuery();
}
 
 
posted @ 2012-03-20 10:41  新旧老顽童  阅读(23)  评论(0编辑  收藏  举报