﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-曾科's Blog-文章分类-ASP.NET</title><link>http://www.blogjava.net/zengke/category/16328.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 06 Jul 2007 03:58:35 GMT</lastBuildDate><pubDate>Fri, 06 Jul 2007 03:58:35 GMT</pubDate><ttl>60</ttl><item><title>Introduce of ASP.NET 2.0 Membership</title><link>http://www.blogjava.net/zengke/articles/128482.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Fri, 06 Jul 2007 01:01:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/128482.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/128482.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/128482.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/128482.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/128482.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 摘要：本文介绍了怎么在ASP.NET 2.0中使用Membership新特性，并且介绍了怎么两种不同的Membership的Provider：ActiveDirectoryMembershipProvider和SqlMembershipProvider，前者是基于微软活动目录服务存储用户信息的，或者是基于SQL SERVER存储的。2.0中的这个新机制大大减少了站点用户认证模块的代码量。目...&nbsp;&nbsp;<a href='http://www.blogjava.net/zengke/articles/128482.html'>阅读全文</a><img src ="http://www.blogjava.net/zengke/aggbug/128482.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2007-07-06 09:01 <a href="http://www.blogjava.net/zengke/articles/128482.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DataGird</title><link>http://www.blogjava.net/zengke/articles/118474.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Fri, 18 May 2007 15:41:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/118474.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/118474.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/118474.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/118474.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/118474.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 12pt">//读取表Supplier并绑定到GridView中<br>private void BindGvSupplier()<br>{<br>OracleConnection conn = this.Conn();<br>OracleCommand cmd = new OracleCommand("select * from Supplier", conn);<br>OracleDataAdapter sda = new OracleDataAdapter(cmd);<br>DataSet ds = new DataSet();<br>sda.Fill(ds, "Supplier");</p>
<p style="FONT-SIZE: 12pt">string[] SuppId = new string[ds.Tables["Supplier"].Rows.Count];<br>for (int i = 0; i &lt; ds.Tables["Supplier"].Rows.Count; i++)<br>{<br>SuppId[i] = ds.Tables["Supplier"].Rows[i][0].ToString();<br>}<br>this.gvSupplier.DataSource = ds.Tables["Supplier"];<br>this.gvSupplier.DataKeyNames[0] = "SuppId";<br>this.gvSupplier.DataBind();<br>this.lblPageIndex.Text = Convert.ToString(int.Parse(this.gvSupplier.PageIndex.ToString()) + 1);<br>this.lblTotalPage.Text = this.gvSupplier.PageCount.ToString();<br>this.lblCount.Text = this.GetTotalCount().ToString();<br>}</p>
<p style="FONT-SIZE: 12pt">//分页触发的事件<br>protected void gvSupplier_PageIndexChanging(object sender, GridViewPageEventArgs e)<br>{<br>this.gvSupplier.PageIndex = e.NewPageIndex;<br>this.BindGvSupplier();<br>this.lblPageIndex.Text = Convert.ToString(int.Parse(this.gvSupplier.PageIndex.ToString()) + 1);<br>this.cbAllSelect_CheckedChanged(this.cbAllSelect, e);<br>}</p>
<p style="FONT-SIZE: 12pt">//删除按钮触发的事件<br>protected void gvSupplier_RowDeleting(object sender, GridViewDeleteEventArgs e)<br>{<br>int id = e.RowIndex;</p>
<p style="FONT-SIZE: 12pt">GridViewRow gvr = this.gvSupplier.Rows[id];<br>int SuppId=int.Parse(((HyperLink)(gvr.Cells[7].Controls[0])).Text.ToString());<br>string sqlString = "delete from Supplier where SuppId=" + SuppId;<br>//如果本页只有一条数据，删除后要向前翻一页<br>if (this.gvSupplier.Rows.Count == 1)<br>{<br>if (this.gvSupplier.PageIndex &gt; 1)<br>{<br>this.gvSupplier.PageIndex--; <br>}<br>}<br>int result = ExecuteSql(sqlString);<br>if (result == 1)<br>{<br>this.Alert("你成功删除一条数据", this.Page);<br>}<br>this.BindGvSupplier();<br>this.BindGvSupplier();</p>
<p style="FONT-SIZE: 12pt">}</p>
<p style="FONT-SIZE: 12pt">//绑定删除按钮的确认提示<br>protected void gvSupplier_RowDataBound(object sender, GridViewRowEventArgs e)<br>{<br>if (e.Row.RowType == DataControlRowType.DataRow)<br>{<br>LinkButton myLb = (LinkButton)(e.Row.Cells[8].Controls[1]);<br>myLb.Attributes.Add("onclick","javascript:return confirm('你确认删除"+e.Row.Cells[0].Text+"吗?')");<br>//鼠标经过时改变行的颜色<br>e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#ffffe7'");<br>e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor='transparent'");<br>}<br>}</p>
<p style="FONT-SIZE: 12pt"><br>//执行一条Oracle语句<br>private int ExecuteSql(String sqlString)<br>{<br>//try<br>//{<br>OracleConnection conn = this.Conn();<br>conn.Open();<br>OracleCommand cmd = new OracleCommand(sqlString, conn);<br>int effectedLine = cmd.ExecuteNonQuery();<br>conn.Close();<br>return effectedLine;<br>//}<br>//catch<br>//{<br>// return 0;<br>//}<br>}</p>
<p style="FONT-SIZE: 12pt"><br>//点击编辑按钮时触发的事件<br>protected void gvSupplier_RowEditing(object sender, GridViewEditEventArgs e)<br>{<br>string s = this.gvSupplier.DataKeys[e.NewEditIndex][1].ToString();<br>this.txtAddr1.Text = "dddd" + s;<br>this.gvSupplier.EditIndex = e.NewEditIndex;<br>this.BindGvSupplier();<br>}<br>//点击取消按钮时触发的事件<br>protected void gvSupplier_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)<br>{<br>this.gvSupplier.EditIndex = -1;<br>this.BindGvSupplier();<br>}<br>//点击更新按钮时触发的事件<br>protected void gvSupplier_RowUpdating(object sender, GridViewUpdateEventArgs e)<br>{<br>int id = e.RowIndex;<br>GridViewRow gvr = this.gvSupplier.Rows[id];<br>int suppId = int.Parse(((HyperLink)(gvr.Cells[7].Controls[0])).Text.ToString());<br>string name = ((TextBox)gvr.Cells[0].Controls[0]).Text.ToString();<br>string status = ((TextBox)gvr.Cells[1].Controls[0]).Text.ToString();<br>string addr1 = ((TextBox)gvr.Cells[2].Controls[0]).Text.ToString();<br>string addr2 =((TextBox) gvr.Cells[3].Controls[0]).Text.ToString();<br>string city = ((TextBox)gvr.Cells[4].Controls[0]).Text.ToString();<br>string state = ((TextBox)gvr.Cells[5].Controls[0]).Text.ToString();<br>string zip=((TextBox)gvr.Cells[6].Controls[0]).Text.ToString();<br>string sqlString = "update Supplier set Name='" + name + "',Status='" + status + "',Addr1='" + addr1 + "',Addr2='" + addr2 + "',City='" + city + "',State='" + state + "',Zip='" + zip + "' where SuppId=" + suppId;<br>int result = ExecuteSql(sqlString);<br>if (result == 1)<br>{<br>//......<br>}<br>this.gvSupplier.EditIndex = -1;<br>this.BindGvSupplier();<br>}</p>
<p style="FONT-SIZE: 12pt"><br>&nbsp;<br>&nbsp;<br>Top <br>&nbsp;<br>&nbsp;回复人：EvilYangs(EvilYang) ( ) 信誉：100 2006-7-14 15:45:21 得分:0 <br>&nbsp;<br>&nbsp;<br>? <br>//增加一条记录<br>protected void btnAdd_Click(object sender, EventArgs e)<br>{<br>string name = this.txtName.Text.ToString();<br>string status = this.txtStatus.Text.ToString();<br>string addr1 = this.txtAddr1.Text.ToString();<br>string addr2 = this.txtAddr2.Text.ToString();<br>string city = this.txtCity.Text.ToString();<br>string state = this.txtState.Text.ToString();<br>string zip = this.txtZip.Text.ToString();<br>string sqlString = "insert into Supplier values(SQSuppId.Nextval,'" + name + "','" + status + "','" + addr1 + "','" + addr2 + "','" + city + "','" + state + "','" + zip + "')";<br>if (this.ExecuteSql(sqlString) == 1)<br>{<br>this.Alert("你成功添加一条数据", this.Page);<br>}<br>else<br>{<br>this.Alert("添加未成功！", this.Page);<br>}<br>this.BindGvSupplier();<br>}</p>
<p style="FONT-SIZE: 12pt">//查看共有多少条数据<br>private int GetTotalCount()<br>{<br>//try<br>//{<br>OracleConnection conn = this.Conn();<br>conn.Open();<br>OracleCommand cmd = new OracleCommand("select count(*) from Supplier", conn);<br>int count = Convert.ToInt32(cmd.ExecuteScalar());<br>conn.Close();<br>return count;<br>//}<br>//catch<br>//{<br>// return 0;<br>//}<br>}</p>
<p style="FONT-SIZE: 12pt">//弹出警告窗口<br>public void Alert(string str_Message, Page page)<br>{<br>page.RegisterStartupScript("", "&lt;script&gt;alert('" + str_Message + "');&lt;/script&gt;");<br>}</p>
<p style="FONT-SIZE: 12pt">//弹出确认对话框<br>public void Confirm(string str_Message, string btn, Page page)<br>{<br>page.RegisterStartupScript("", "&lt;script&gt; if (confirm('" + str_Message + "')==true){document.forms(0)." + btn + ".click();}&lt;/script&gt;");<br>} </p>
<p style="FONT-SIZE: 12pt">protected void cbAllSelect_CheckedChanged(object sender, EventArgs e)<br>{<br>for(int i=0;i&lt;this.gvSupplier.Rows.Count;i++)<br>{<br>CheckBox cbSelect=(CheckBox)(gvSupplier.Rows[i].Cells[10].FindControl("cbSelect"));<br>cbSelect.Checked=this.cbAllSelect.Checked;<br>}<br>}</p>
<p style="FONT-SIZE: 12pt">//当点击删除按钮时删除所有checkbox被选中的数据<br>protected void btnDel_Click(object sender, EventArgs e)<br>{<br>//如果用户确认将触发btnRealDel的事件<br>this.Confirm("你真的要删除你所选的数据么？", "btnRealDel", this.Page);</p>
<p style="FONT-SIZE: 12pt">}</p>
<p style="FONT-SIZE: 12pt">//真实的删除操作<br>public void btnRealDel_Click(object sender, EventArgs e)<br>{<br>int count = 0;<br>for (int i = 0; i &lt; this.gvSupplier.Rows.Count; i++)<br>{<br>CheckBox myCb = (CheckBox)(this.gvSupplier.Rows[i].Cells[10].FindControl("cbSelect"));<br>if (myCb.Checked)<br>{<br>count++;<br>HyperLink hl = (HyperLink)(this.gvSupplier.Rows[i].Cells[7].Controls[0]);<br>int suppId = int.Parse(hl.Text.ToString());<br>string sqlString = "delete from Supplier where SuppId=" + suppId;<br>this.ExecuteSql(sqlString);<br>}<br>}<br>if (count &gt; 0)<br>{<br>this.Alert("你成功删除了" + count + "条数据", this.Page);<br>this.BindGvSupplier();<br>} <br>}</p>
<img src ="http://www.blogjava.net/zengke/aggbug/118474.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2007-05-18 23:41 <a href="http://www.blogjava.net/zengke/articles/118474.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>运用asp2.0创建和使用三层数据架构(C#)--【第一篇：简介之建立数据访问层】 </title><link>http://www.blogjava.net/zengke/articles/104741.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Mon, 19 Mar 2007 07:20:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/104741.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/104741.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/104741.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/104741.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/104741.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 简介		在本次学习中，我们将会从最基本的开始，建立一个数据访问层，DAL（Data Access Layer），使用DataSets类，来访问数据库中的信息。随着互联网的发展，我们的生活总是在带有数据的工作中进行的。我们建立数据库来存储数据，编写代码来取回或者更改它们，并且我们制作页面来收集汇总这些数据。这是我们的漫长学习中的第一课，我们将会来探究在asp2.0中实现这些常用的模式的技术。我们...&nbsp;&nbsp;<a href='http://www.blogjava.net/zengke/articles/104741.html'>阅读全文</a><img src ="http://www.blogjava.net/zengke/aggbug/104741.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2007-03-19 15:20 <a href="http://www.blogjava.net/zengke/articles/104741.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网页防刷新重复提交、防后退解决方法</title><link>http://www.blogjava.net/zengke/articles/89283.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Thu, 21 Dec 2006 06:46:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/89283.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/89283.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/89283.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/89283.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/89283.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">提交后禁用提交按钮（大部分人都是这样做的）</font>
		</p>
		<p>
				<font size="2">如果客户提交后,按F5刷新怎么办?</font>
		</p>
		<p>
				<font size="2">使用Session</font>
		</p>
		<p>
				<font size="2">在提交的页面也就是数据库处理之前：</font>
		</p>
		<p>
				<font size="2">
				</font> </p>
		<p>
				<font size="2">if session("ok")=true then<br />   response.write "错误，正在提交"<br />   response.end<br />end if</font>
		</p>
		<font size="2">
				<p>
						<br />数据处理完后，修改session("ok")=false。</p>
				<p>数据处理成功马上Redirect到另外一个页面</p>
				<p>操作后刷新的确是个问题，你可以使用跳转页面、关闭本页面，如果是有参数据条件来控制的，那就应该好做了，可以直接修改window.location的值，把参数全部改掉，这样就差不多了。 </p>
				<p>缺点：简单地运用Response.Redirect将不再有效，因为用户从一个页面转到另一个页面，我们都必须用客户端代码清除location.history。注意，这种方法清除的是最后一个访问历史记录，而不是全部的访问记录。 点击后退按钮，再点击后退按钮，你可以看到这时打开的是本页面之前的页面！（当然，这是在你的客户端启用了JavaScript功能的条件下。） </p>
				<p>如果客户按后退，怎么办？</p>
				<p>防止网页后退--禁止缓存</p>
				<p>我们在进行数据库添加操作的时候，如果允许后退，而正巧有刷新了页面，就会再次执行添加操作，无疑这不是我们需要的，像一般网上很多禁止缓存的代码，有时并不可靠，这时你只要在操作的页面加上就可以了，在网页的里指定要定向的新页，再点后退，看是不是不会再退到刚才的操作页面了，实际上已经把这个历史给删除了 </p>
				<p>ASP：<br />Response.Buffer = True    <br />Response.ExpiresAbsolute = Now() - 1    <br />Response.Expires = 0    <br />Response.CacheControl = "no-cache"</p>
				<p>ASP.NET：<br />Response.Buffer=true;<br />Response.ExpiresAbsolute=DateTime.Now.AddSeconds(-1);<br />Response.Expires=0;<br />Response.CacheControl="no-cache";</p>
				<p>究竟怎样才能"禁用"浏览器的后退按钮？或者“怎样才能防止用户点击后退按钮返回以前浏览过的页面？”</p>
				<p>遗憾的是，我们无法禁用浏览器的后退按钮。</p>
				<p>防止网页后退--新开窗口</p>
				<p>用window.open弹出表单页面，点提交后关闭该页；处理提交的ASP页也是用弹出，设定表单的target,点提交时window.open("XXX.asp","_blank"),然后用JS来提交表单，完成后window.close()；<br />简单的说，就是提交表单的时候弹出新窗口，关闭本窗口。对于window.open()打开的窗口怎么后退？能后退到哪里去？</p>
				<p>呵呵，罗嗦了一堆废话，知道怎么处理了么？混合运用客户端脚本和服务器端脚本。<br /></p>
		</font>
		<p align="left">
				<font size="2">
				</font> </p>
<img src ="http://www.blogjava.net/zengke/aggbug/89283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2006-12-21 14:46 <a href="http://www.blogjava.net/zengke/articles/89283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual Studio .NET文件格式一览</title><link>http://www.blogjava.net/zengke/articles/81464.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Thu, 16 Nov 2006 02:57:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/81464.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/81464.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/81464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/81464.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/81464.html</trackback:ping><description><![CDATA[
		<font size="2">.sln：解决方案文件，为解决方案资源管理器提供显示管理文件的图形接口所需的信息。 <br />.csproj:项目文件，创建应用程序所需的引用、数据连接、文件夹和文件的信息。 <br />.aspx：Web 窗体页由两部分组成：视觉元素（HTML、服务器控件和静态文本）和该页的编程逻辑。Visual Studio 将这两个组成部分分别存储在一个单独的文件中。视觉元素在.aspx 文件中创建。 <br />.aspx.cs：Web 窗体页的编程逻辑位于一个单独的类文件中，该文件称作代码隐藏类文件（.aspx.cs）。 <br />.cs： 类模块代码文件。业务逻辑处理层的代码。 <br />.asax：Global.asax 文件（也叫做 ASP.NET 应用程序文件）是一个可选的文件，该文件包含响应 ASP.NET 或 HTTP 模块引发的应用程序级别事件的代码。 <br />.config：Web.config 文件向它们所在的目录和所有子目录提供配置信息。 <br />.aspx.resx/.resx：资源文件，资源是在逻辑上由应用程序部署的任何非可执行数据。通过在资源文件中存储数据，无需重新编译整个应用程序即可更改数据。 <br />.XSD:XML schema的一种.从DTD,XDR发展到XSD <br />.pdb:PDB（程序数据库）文件保持着调试和项目状态信息，从而可以对程序的调试配置进行增量链接。 <br />.suo:解决方案用户选项,记录所有将与解决方案建立关联的选项，以便在每次打开时，它都包含您所做的自定义设置。 <br />.asmx:asmx 文件包含 WebService 处理指令，并用作 XML Web services 的可寻址入口点 <br />.vsdisco（项目发现）文件 基于 XML 的文件，它包含为 Web 服务提供发现信息的资源的链接 (URL)。 <br />.htc:一个HTML文件,包含脚本和定义组件的一系列HTC特定元素.htc提供在脚本中implement组件的机制 <br />.ascx 是用户控件代码文件<br />.aspx webform html脚本文件<br />.cs 是c#类文件)<br />.vb 是vb类文件)<br />.aspx.cs 和你的webform相关的后台c#代码文件,同.cs<br />.aspx.vb 和你的webform相关的后台VB代码文件,同.vb</font>
		<p>
				<font color="#000000">
				</font> </p>
<img src ="http://www.blogjava.net/zengke/aggbug/81464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2006-11-16 10:57 <a href="http://www.blogjava.net/zengke/articles/81464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET中文件上传下载方法集合</title><link>http://www.blogjava.net/zengke/articles/76765.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Mon, 23 Oct 2006 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/76765.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/76765.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/76765.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/76765.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/76765.html</trackback:ping><description><![CDATA[
		<p>文件的上传下载是我们在实际项目开发过程中经常需要用到的技术，这里给出几种常见的方法，本文主要内容包括： </p>
		<p>　　1、如何解决文件上传大小的限制 </p>
		<p>　　2、以文件形式保存到服务器 </p>
		<p>　　3、转换成二进制字节流保存到数据库以及下载方法 </p>
		<p>　　4、上传Internet上的资源 </p>
		<p>　　第一部分： </p>
		<p>　　首先我们来说一下如何解决ASP.net中的文件上传大小限制的问题，我们知道在默认情况下ASP.NET的文件上传大小限制为2M，一般情况下，我们可以采用更改Web.Config文件来自定义最大文件大小，如下： </p>
		<p>　　这样上传文件的最大值就变成了4M，但这样并不能让我们无限的扩大 MaxRequestLength的值，因为ASP.NET会将全部文件载入内存后，再加以处理。解决的方法是利用隐含的 HttpWorkerRequest，用它的GetPreloadedEntityBody和ReadEntityBody方法从IIS为ASP.NET 建立的pipe里分块读取数据。实现方法如下： </p>
		<p>IServiceProvidERProvider=(IServiceProvider)HttpContext.Current; <br />HttpWorkerRequestwr=(HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest)); <br />byte[]bs=wr.GetPreloadedEntityBody(); <br />. <br />if(!wr.IsEntireEntityBodyIsPreloaded()) <br />{ <br />　intn=1024; <br />　byte[]bs2=newbyte[n]; <br />　while(wr.ReadEntityBody(bs2,n)&gt;0) <br />　{ <br />　　.. <br />　} <br />} </p>
		<p>　　这样就可以解决了大文件的上传问题了。 </p>
		<p>　　第二部分：</p>
		<p>　　下面我们来介绍如何以文件形式将客户端的一个文件上传到服务器并返回上传文件的一些基本信息。 </p>
		<p>　　首先我们定义一个类，用来存储上传的文件的信息（返回时需要）。 </p>
		<p>public class FileUpLoad <br />{ <br />　public FileUpLoad() <br />　{} <br />　/**//// <br />　/// 上传文件名称 <br />　/// BR&gt;　public string FileName <br />　{ <br />　　get <br />　　{ <br />　　　return fileName; <br />　　} <br />　　set <br />　　{ <br />　　　fileName = value; <br />　　} <br />　} <br />　private string fileName; </p>
		<p>　/**//// <br />　/// 上传文件路径 <br />　/// BR&gt;　public string FilePath <br />　{ <br />　　get <br />　　{ <br />　　　return filepath; <br />　　} <br />　　set <br />　　{ <br />　　　filepath = value; <br />　　} <br />　} <br />　private string filepath; </p>
		<p>　/**//// <br />　/// 文件扩展名 <br />　/// BR&gt;　public string FileExtension <br />　{ <br />　　get <br />　　{ <br />　　　return fileExtension; <br />　　} <br />　　set <br />　　{ <br />　　　fileExtension = value; <br />　　} <br />　} <br />　private string fileExtension; <br />} </p>
		<p>　　另外我们还可以在配置文件中限制上传文件的格式(App.Config)：</p>
		<p>＜?XML version="1.0" encoding="gb2312" ?&gt; <br />＜Application&gt; <br />＜FileUpLoad&gt;<br />＜Format&gt;.jpg|.gif|.png|.bmp<br />＜/FileUpLoad&gt; <br />＜/Application&gt;</p>
		<p>　　这样我们就可以开始写我们的上传文件的方法了，如下： </p>
		<p>public FileUpLoad UpLoadFile(HtmlInputFile InputFile,string filePath,string myfileName,bool isRandom) <br />{ <br />　FileUpLoad fp = new FileUpLoad(); <br />　string fileName,fileExtension; <br />　string saveName; </p>
		<p>　// <br />　//建立上传对象 <br />　// <br />　HttpPostedFile postedFile = InputFile.PostedFile; </p>
		<p>　fileName = System.IO.Path.GetFileName(postedFile.FileName); <br />　fileExtension = System.IO.Path.GetExtension(fileName); </p>
		<p>　// <br />　//根据类型确定文件格式 <br />　// <br />　AppConfig app = new AppConfig(); <br />　string format = app.GetPath("FileUpLoad/Format"); </p>
		<p>　// <br />　//如果格式都不符合则返回 <br />　// <br />　if(format.IndexOf(fileExtension)==-1) <br />　{ <br />　　throw new ApplicationException("上传数据格式不合法"); <br />　} </p>
		<p>　// <br />　//根据日期和随机数生成随机的文件名 <br />　// <br />　if(myfileName != string.Empty) <br />　{ <br />　　fileName = myfileName; <br />　} </p>
		<p>　if(isRandom) <br />　{ <br />　　Random objRand = new Random(); <br />　　System.DateTime date = DateTime.Now; <br />　　//生成随机文件名 <br />　　saveName = date.Year.ToString() + date.Month.ToString() + date.Day.ToString() + date.Hour.ToString() + date.Minute.ToString() + date.Second.ToString() + Convert.ToString(objRand.Next(99)*97 + 100); <br />　　fileName = saveName + fileExtension; <br />　} </p>
		<p>　string phyPath = HttpContext.Current.Request.MapPath(filePath); </p>
		<p>　//判断路径是否存在,若不存在则创建路径 <br />　DirectoryInfo upDir = new DirectoryInfo(phyPath); <br />　if(!upDir.Exists) <br />　{ <br />　　upDir.Create(); <br />　} </p>
		<p>　// <br />　//保存文件 <br />　// <br />　try <br />　{ <br />　　postedFile.SaveAs(phyPath + fileName); </p>
		<p>　　fp.FilePath = filePath + fileName; <br />　　fp.FileExtension = fileExtension; <br />　　fp.FileName = fileName; <br />　} <br />　catch <br />　{ <br />　　throw new ApplicationException("上传失败!"); <br />　} </p>
		<p>　//返回上传文件的信息 <br />　return fp; <br />} </p>
		<p>　　然后我们在上传文件的时候就可以调用这个方法了，将返回的文件信息保存到数据库中，至于下载，就直接打开那个路径就OK了。 </p>
		<p>　　第三部分：</p>
		<p>　　这里我们主要说一下如何以二进制的形式上传文件以及下载。首先说上传，方法如下： </p>
		<p>public byte[] UpLoadFile(HtmlInputFile f_IFile) <br />{ <br />　//获取由客户端指定的上传文件的访问 <br />　HttpPostedFile upFile=f_IFile.PostedFile; <br />　//得到上传文件的长度 <br />　int upFileLength=upFile.ContentLength; <br />　//得到上传文件的客户端MIME类型 <br />　string contentType = upFile.ContentType; <br />　byte[] FileArray=new Byte[upFileLength]; </p>
		<p>　Stream fileStream=upFile.InputStream; </p>
		<p>　fileStream.Read(FileArray,0,upFileLength); <br />　return FileArray; <br />} </p>
		<p>　　这个方法返回的就是上传的文件的二进制字节流，这样我们就可以将它保存到数据库了。下面说一下这种形式的下载，也许你会想到这种方式的下载就是新建一个 aspx页面，然后在它的Page_Load()事件里取出二进制字节流，然后再读出来就可以了，其实这种方法是不可取的，在实际的运用中也许会出现无法打开某站点的错误，我一般采用下面的方法： </p>
		<p>　　首先，在Web.config中加入： </p>
		<p>＜add verb="*" path="openfile.aspx" type="RuixinOA.Web.BaseClass.OpenFile, RuixinOA.Web"/&gt;</p>
		<p>　　这表示我打开openfile.aspx这个页面时，系统就会自动转到执行RuixinOA.Web.BaseClass.OpenFile 这个类里的方法，具体实现如下： </p>
		<p>using System; <br />using System.Data; <br />using System.Web; <br />using System.IO; <br />using Ruixin.WorkFlowDB; <br />using RXSuite.Base; <br />using RXSuite.Component; <br />using RuixinOA.BusinessFacade; </p>
		<p>namespace RuixinOA.Web.BaseClass <br />{ <br />　/**//// <br />　/// NetUFile 的摘要说明。 <br />　/// BR&gt;　public class OpenFile : IHttpHandler <br />　{ <br />　　public void ProcessRequest(HttpContext context) <br />　　{ <br />　　　//从数据库中取出要下载的文件信息 <br />　　　RuixinOA.BusinessFacade.RX_OA_FileManager os = new RX_OA_FileManager(); <br />　　　EntityData data = os.GetFileDetail(id); </p>
		<p>　　　if(data != null &amp;&amp; data.Tables["RX_OA_File"].Rows.Count &gt;0) <br />　　　{ <br />　　　　DataRow dr = (DataRow)data.Tables["RX_OA_File"].Rows[0]; <br />　　　　context.Response.Buffer = true; <br />　　　　context.Response.Clear(); <br />　　　　context.Response.ContentType = dr["CContentType"].ToString(); <br />　　　　context.Response.AddHeader("Content-Disposition","attachment;filename=" + HttpUtility.UrlEncode(dr["CTitle"].ToString())); <br />　　　　context.Response.BinaryWrite((Byte[])dr["CContent"]); <br />　　　　context.Response.Flush(); <br />　　　　context.Response.End(); <br />　　　} <br />　　} <br />　　public bool IsReusable <br />　　{ 　 <br />　　　get { return true;} <br />　　} <br />　} <br />} </p>
		<p>　　执行上面的方法后，系统会提示用户选择直接打开还是下载。这一部分我们就说到这里。 </p>
		<p>　　第四部分：</p>
		<p>　　这一部分主要说如何上传一个Internet上的资源到服务器。 </p>
		<p>　　首先需要引用 System.Net 这个命名空间，然后操作如下： </p>
		<p>HttpWebRequest hwq = (HttpWebRequest)WebRequest.Create("<a href="http://localhost/pwtest/webform1.aspx">http://localhost/pwtest/webform1.aspx</a>"); <br />HttpWebResponse hwr = (HttpWebResponse)hwq.GetResponse(); <br />byte[] bytes = new byte[hwr.ContentLength]; <br />Stream stream = hwr.GetResponseStream(); <br />stream.Read(bytes,0,Convert.ToInt32(hwr.ContentLength)); <br />//HttpContext.Current.Response.BinaryWrite(bytes); </p>
		<p>　　HttpWebRequest 可以从Internet上读取文件，因此可以很好的解决这个问题。 <br /></p>
<img src ="http://www.blogjava.net/zengke/aggbug/76765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2006-10-23 15:28 <a href="http://www.blogjava.net/zengke/articles/76765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>创建ASP.NET项目时报：http://1.1 400 bad Request错误</title><link>http://www.blogjava.net/zengke/articles/75552.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Tue, 17 Oct 2006 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/75552.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/75552.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/75552.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/75552.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/75552.html</trackback:ping><description><![CDATA[
		<font size="2">(1)   <br />将Asp.net在ＩＩＳ中重新注册   <br />cd   C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322   <br />aspnet_regiis   -i   <br />(2)   <br />IIS管理器中,将“默认网站”－“属性”－“网站”，将“ＩＰ地址”改为“（全部未分配）”   <br />(3)   <br />点击“ＷＥＢ服务扩展”，将“ASP.NET   v1.1.4322   ”改为“允许”。</font>
<img src ="http://www.blogjava.net/zengke/aggbug/75552.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2006-10-17 10:25 <a href="http://www.blogjava.net/zengke/articles/75552.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>三层式开发中的层次划分讨论[转自：CSDN_lubosun(大白菜)]</title><link>http://www.blogjava.net/zengke/articles/75371.html</link><dc:creator>曾科</dc:creator><author>曾科</author><pubDate>Mon, 16 Oct 2006 03:17:00 GMT</pubDate><guid>http://www.blogjava.net/zengke/articles/75371.html</guid><wfw:comment>http://www.blogjava.net/zengke/comments/75371.html</wfw:comment><comments>http://www.blogjava.net/zengke/articles/75371.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zengke/comments/commentRss/75371.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zengke/services/trackbacks/75371.html</trackback:ping><description><![CDATA[
		<font size="2">先举一个曾经在哪本书上看到的例子：现在你想在1米宽的小溪上建一座桥，你会在上面放块木板就完了。如果想在宽一点的小河上建这桥，你就需要计算木材用料，价格等，如果需要别人帮忙，你还要多一些图纸什么的让别人理解你的想法。现在你要在大江上面建桥，你需要有整体的计划，包括各个方面，比如将来可能的收费和利益分配等问题。 <br />这里讲3层式，其实是针对“大江上面建桥”来的，对于1米宽的小溪，在实际中可能一点用都没有。不过现在我不可能去拿个长江大桥作例子来讲，所以这里还是用这条简单的小溪，讲讲怎么建桥。之所以讲这么多废话，是为了防止部分人看完此文之后“小小一个东西，搞那么麻烦干什么。。”其实这里讲的不是具体的这个例子，而是分层的思想，理解这点非常重要。 <br />下面我就我们大家日常见最多的例子来讲，就是“用户登录”的例子。这个例子很简单，但是麻雀虽小五脏俱全。从数据访问到业务规则到界面全有了。 <br />本文分2个部分，如果只想研究面向对象的思想，对实现已经熟悉，可以跳过第一部分。 <br />第一部分 <br />新建一个空白解决方案。然后： <br />“添加”－“新建项目”－“其他项目”－“企业级模版项目”－“C#生成块”－“数据访问”（数据层，下简称D层） <br />“添加”－“新建项目”－“其他项目”－“企业级模版项目”－“C#生成块”－“业务规则”（业务层，下简称C层） <br />“添加”－“新建项目”－“其他项目”－“企业级模版项目”－“C#生成块”－“Web用户界面”（界面层，下简称U层） <br />右键点“解决方案”－“项目依赖项”，设置U依赖于D、C，C依赖于D。 <br />对U添加引用D、C，对C添加引用D。 <br />到此为止，一个三层的架子建立起来了。我上面说的很具体很“傻瓜”，知道的人觉得我废话，其实我这段时间很强烈的感觉到非常多的人其实对这个简单的过程完全不了解。虽然不反对建2个“空项目”和1个“Asp net Web应用程序项目”也可以作为3层的框架，而且相当多的人认为其实这些“企业级模板项目”其实就是个空项目，这是一个误区。没错，企业级模板项目你从解决方案资源管理器里看它是个什么也没有的，但是你可以用记事本打开项目文件，看见不同了吧？？有些东西在背后，你是看不见的，不过系统已经做好了。也就是说，如果你在C层里的某个类里“using System Data SqlClineit”，或者使用一个SqlConnection对象，编译时候不会出错，但是会在“任务列表”里生成一些“策略警告”，警告你在C层里不要放应该放在D层的东西（虽然就程序来说没错，但是可读性可维护性就打了折扣）而这种功能，空项目是无法給你的。 <br />我们知道建桥需要砖块，应该是先准备好砖再来建桥，不过为了讲解上的顺序性和连贯性，简单性。我们先建桥，建的过程中需要砖块再现做，这样就不会多出来“桥不需要的东西”。注意在实际中，还是应该先准备砖块。 <br />U层其实就是桥，C层是砖块，D层是原料（石头、沙子）。这也解释前面为什么U层要引用、依赖D层（而不是U对C，C对D的层次），因为桥除了需要砖头，其实也需要石头沙子。 <br />我们在U层建一个Login aspx（这里插入一句，我不喜欢去把系统自动生成的WebForm1 aspx拿来改成login或index或直接删除，我一般留着它当测试代码用，等到整个系统冻结再把它移除就可以了。）添加1个TextBox（id=txt），一个DropDownList（id=ddl），一个Button(id=btn)。其中DropDownList用来选择用户名，button是提交按钮， TextBox用来输入密码。 <br />现在我们必须要添加的代码分为2部分： 1、Page_load时对ddl的初始化。2、btn的click处理。 <br />1： <br />private void Page_Load(object sender, System.EventArgs e) <br />{ <br />if(!IsPostBack) <br />{ <br />this.ddl.DataSourse=DataManager.GetOneColunm(“User”,”uid”); //讲解1 <br />this.ddl.DataBind(); <br />} <br />} <br />2： <br />private void Btn_Click(object sender, System.EventArgs e) <br />{ <br /> string uid=this.ddl.SelectedValue; <br /> string psw=this.txt.Text; <br /> if(psw =””) <br />  MessageBox(“空密码！”); <br /> else <br /> { <br />  User theUser; <br />  try <br />  { <br />   theUser=new User(uid); //讲解2 <br />  } <br />  catch(Exception e) <br />  { <br /> MessageBox(e. Message);//讲解2 <br /> return; <br />} <br />if(theUser.CheckPsw(psw)) //讲解3 <br />{ <br /> theUser.SetSessions(); <br /> Response.Redirect(“……………..”);  //登录成功！  <br />} <br />else <br />{ <br /> MessageBox(“密码错误！”);  <br />} <br /> } <br />} <br />讲解1：DataManager 是D层中的一个类，提供常见的数据操作。GetOneColunm(string Table,string Colunm)方法返回一个只有1列的DataTable，值为数据库中表名为Table，的Colunm列。 <br />public class DataManager <br />{ <br /> public DataManager() <br /> { <br /> } <br /> public static DataTable GetOneColunm(string Table,string Colunm) <br /> { <br />  //此处省略相关代码。返回指定表指定列 <br /> } <br />} <br />其实这个地方演示的是在U层直接绕过C层访问D层的例子，因为该结构逻辑上很简单，而且获取用户名并不是现实社会中的业务逻辑的一部分（仅仅是界面需要，因为在这里其实用成2个TextBox的话完全不需要这一步） <br />讲解2：定义一个User类的实例。User类的定义可能如下： <br />public class User <br />{ <br /> public User(string uid) <br /> { <br />  if(DataManager.IsIn(“user”,”uid=’"+uid+”’”)) <br />   throw "用户不存在"; <br />  else<br />   //User()其他初始化; <br /> } <br /> public bool CheckPsw(string psw) <br /> { <br />  if(DataManager.IsIn(“user”,”uid=’"+uid+”’ and psw=’”+psw+”’”)) <br />   return true; <br />  else <br />   return false; <br /> } <br />} <br />注意到用户类构造函数中用了个throw来抛出用户不存在的异常，在下面catch的时候用MessageBox(e. Message);来弹出“用户不存在”的错误。这里其实也是为了演示一个层间传递信息的手段，异常也是一种手段，虽然在这里其实可以有其他方式比如返回值，引用参数之类的直接用一个方法来获得用户是否存在的信息，没必要放在构造里，我这么做只是为了演示传递过程，在后面的有讨论这种用法在分层模式下某种特殊情况的应用以解决一些问题。这个类里又用了DataManager类的一个静态方法IsIn(string Table,string str)该方法其实其实是执行 “select * from Table where str” <br />这个Sql语句并在返回空的时候方法返回false，否则返回true。一个很简单的方法。这里演示了C层对D层的调用。 <br />顺便说一句，因为在VS.Net中，项目的名称会默认地成为项目中的namespace，可以通过把所有自动生成的代码中的namespace改为“解决方案名称”来使3个层可以无缝地自由调用。或者在调用的地方using一下其他层的空间名，看个人喜欢了。比如上面的Login.aspx.cs里需要using2个，而User.cs里要using一个。 <br />讲解3：这里的检查用户密码同样用到User类的一个方法CheckPsw（）而这个方法 又用到了IsIn（）这里就不多说了。 <br />大家注意到我们在U层的页面里用MessageBox()方法来弹出对话框，其实这个方法写在PageBase.cs里，是U层的另外一个文件，继承Page类，Login类又继承它，这个方法其实是把Response.Write(“&lt;script&gt;alert(\“”+ msg+“\”)&lt;/script&gt;”)封装起来了。 <br />到此为止，登录结束，例子的实现也说完了。不过只讲了“然”，没有讲“所以然”。下面开始讲“所以然”。 <br />第二部分 <br />作为对比，我们使用一个不面向对象的，不分层的Asp式的Aspx相同登录作为对比。具体的Asp代码我就不写了，反正登录哪都有。先来看看他们2者发生的遭遇（这是不幸的，却偏偏是经常发生的）： <br />1、  项目经理突然说“不用SqlServer了，换成Access”（正版费用问题）。看看2边分别发生什么：3层这边（A），把DataManager类里的连接改改（在实际情况下，极可能其实是改它的基类，它本身不用改），Web.config中把字符串换掉就完了。Asp式那边（B），同样要改Web.config，同样要改连接什么的，修改量在这个具体的“小溪”例子上几乎相同，在“大桥”例子上B应该会稍微多改点，不过也不会多很多。但是！请注意一点，我们在修改代码的时候，主要时间和精力不是花在“改”这个动作上，而是花在“要改什么地方”上和“寻找需要改的地方”上。在“大桥”上，B需要花费多的多的时间，对大部分文件进行查找和替换。A则仅仅在数据层里，另外2个层不需要任何修改。从这个角度出发我们想到2点原则： <br />a)    数据层必须要能够保证数据库的变动（任何结构变动、类型变动）对其余各层的不透明性。也就是数据库怎么变，其他层绝对不应该变哪怕1行代码！（web.config是整个应用程序的配置，虽然在物理上存在于U层的文件夹中，但个人更愿意认为它是独立的不属于任何层的，所以这里不计它） <br />b)    数据层越小越好（如果没有这点原则，我们把整个所有的东西都放在数据层，那当然数据库变动对外面无影响――因为外面几乎没东西――但是这显然不可行）。而且因为前面我们说了，大部分时间花在“找”上面，你小点，找起来也容易点。 <br />2、  客户突然提出B/S版的不好，要换成C/S版的。对于（B）来说，这是晴天霹雳！！他的所有工作都要重新做，（或者几乎所有工作），虽然他有很多代码还可以用，不过他在未来一小段时间就必须不断在“复制－粘贴”中使用以前的代码。（A）发生了什么？？如果你细心看会发现（A）之需要新建个项目“Windows用户界面”（和前面一样，添加引用，项目依赖），拖几个控件到上面，把控件名字起成txt，ddl，btn，然后把click代码和Pageload代码复制过去，（居然。。。）连1行代码都不需要修改！！！！当然，这是比较极端的例子（win和web都有TextBox，DropDownList，Button3种控件，而且我们在PageBase里定义的方法MessageBox()又刚好和win里面方法同名。。。）不过尽管有这么多巧合我们仍然可以也愿意相信，在“大桥”上，（A）将比（B）少做很多工作。从这个角度出发我们又想到2点类似原则： <br />a)    界面层应该保证界面的任何变化都不需要修改其他层的内容（不管这个具体的例子把ddl改为另外一个TextBox，或是把B/S改为C/S） <br />b)    界面层越小越好（理由同上。） <br />3、  除开了界面层和数据层，（如果你的方案中只有3个层的话）剩下的就都是逻辑层的内容了。所以和前面的相对应，我们可以得出结论： <br />a)    逻辑层应当不受数据库和界面变动的影响而需要修改。 <br />b)    逻辑层越大越好（因为另外2层越小越好。。。） <br />有了最基本的原则，我们应该来讨论下，根据原则，要怎么分层的问题： <br />1、  PageBase.cs 应该放在哪个层？根据上面的原则，应该放在C层。但是实际上我习惯放在U层，或者放在另外一个（第4个层，通用底层，在比数据层还低的位置）层里。到底放在什么地方，我最开始的做法是在C层，因为按上面归纳的原则，就应该放在C，但是后来一段时间我习惯于“四层式”之后就把它放在通用底层（下简称B层，该层同时也放如本来在D层中的SqlHelper类等，包括原来3层中所有“通用”的类，这里通用的意思是说其他系统也可以用的到而不需要修改，这个层通常不用解决方案名称而用公司、小组名称等作为namespace，在有新项目的时候在建解决方案的时候就可以“添加现有项目”，简单的加进去并不断积累，实践中对提高效率和代码重用有比较大作用。）不过如果只有3层，我现在倾向于把PageBase放在U层。主要因为最近一段潜心研究面向对象的分析设计的心得。说起来又是一大匹布没完，不过我又在前面的“原则”上加1条：“如果某个类，仅为了某层的某种特殊实现而存在，那么它必须放在该层”，比如PageBase是为了U层的特殊实现（B/S实现）而存在，又比如SqlHelper是为了D层的特殊实现（SqlServer数据库）而存在。所以对应的，它们必须分别放在U层和D层（如果不加这条的话按前面他们都该放在C层，因为C层越大越好，而且数据库和界面的变动不需要改动这2个类－虽然它们可能因改动而没有用了，不过还是不需要去修改它们） <br />2、  Oldjacky曾经和我谈到一个问题：Datagrid中允许作删除操作，但是如果当前仅余下最后一条记录，则不允许这个删除操作！那么该删除应该放在C层还是D层还是U层？我觉得应该从另外一个角度来考虑： <br />a)    这种“不允许”是“业务规则的不允许”（比如表内的数据表示当前在店里的职员，删除表示职员离开店里－可能去拿货什么的，添加表示职员回来，当柜台只有一名职员时，显然他绝对不能离开去送货），这个时候，此“禁止删除”的操作应该产生在C层。 <br />b)    这种“不允许”是“程序实现的不允许”（比如当这里为空的时候会引起其他地方比如ToString()方法产生“未将对象的引用设置到对象的实例……”的错误，或程序设计者或项目经理的主观愿望希望它“不允许”以此来减少工作量或简化程序）。这个时候，此“禁止删除”可以放在U层（比如上面说的ToString）或D层（比如违反数据库约束） <br />3、  细心的人可能会发现，前面的登录例子里，用户一共可以获得3种弹出错误分别是“空密码”“密码错误”“用户不存在”，而其中前2个是在U层里做的，“用户不存在”却是在C层里做的（我是指这个字符串）还是开始说的建桥，我这里是用“小溪建桥”来讲解“大江建桥”所以故意在这里转了个没用的圈，就像在计算小溪上这块木板到底够用多少年，其实对小溪没什么意义，只是为了讲解大桥需要而加上去的，毕竟大桥需要这种考虑。我这里假设“用户不存在需要弹出提示”是一种业务逻辑上的需要，而“未输入密码需要提示”则不是业务规则需要（比如实际业务中可以允许空密码，但是项目经理不同意，说一定要密码）在这个登录例子中其实根本没有什么问题，但是在大项目里，如果这个东西不是业务规则的需要，就不应该放在业务层，如果是一种业务规则，就要放在业务层。有助于业务模型与现实实体的衔接，也有益于业务逻辑更好地表现现实实体的特征。 <br />到此为止，我再次归纳出我们的最终的原则： <br />1、  如果某个类，仅为了某层的某种特殊实现而存在，那么它必须放在该层。 <br />2、  数据层应当在保证数据库变化对其他层不可见的前提下尽量小。 <br />3、  界面层应当在保证界面变化对业务逻辑层不影响的前提下尽量小。 <br />4、  如果某个类不是业务规则的需要，就不应该放在业务层，反之亦然。 <br />5、  逻辑层应当在保证数据库或界面变化不会造成自身影响的前提下尽量大。 <br />以上5点如果发生冲突，在找平衡点的时候，前面的要高于后面的。比如1和3冲突的时候更倾向于使用规则1。 <br />第二部分结束 <br />有一点应该是“编程代码习惯”和“面向对象”的范畴，不过因为和分层有些关系，所以也说一下。“如果你的代码，自己把它翻译成中文并加必要的标点符号后，其他不懂程序的人看了仍然觉得很乱，那么你很可能层没分好”。比如前面的btn的click： <br />｛ <br />字符串 用户名是 下拉框 选择值； <br />字符串 密码是 输入框 值； <br />如果 密码是 空 <br /> 对话框（密码空！）； <br />否则 <br />｛ <br /> 用户 这用户； <br /> 尝试 <br />｛ <br /> 这用户 是 新的 用户（用户名）； <br />｝ <br />捕捉（错误） <br />｛ <br /> 对话框（错误 消息）； <br /> 返回； <br />｝ <br />如果 这用户检查密码（密码） <br />{ <br /> 这用户 设置状态； <br /> 响应 重定位（“。。。。。”）； <br />} <br />否则 <br />{ <br /> 对话框（密码错误） <br />} <br />｝ <br />代码最好能让不懂的人也能看懂到底在干什么。 <br />最后，oldjacky的Datagrid删除的例子“删除”显然在D层，但是不允许却可能在C或U，如果在U没什么说的了，如果在C，那么这种“不允许”的一个比较合理的实现方法就是在C层里遇到这种情况throw一下。当U层里catch到该throw的时候，禁止删除操作，这样当2个层同时有原因引起禁止时，可以从代码一眼看出这种禁止的来源。类似于前面的2种弹出错误。 <br />注：本文为原创，甚至在写本文的时候，并没有看任何网页文章和书，完全是一时之作，错误难免，而且连代码也是在写字板上打出来的，所以不见得可以运行，大小写也可能有错。一口气写这么多，行文很乱，废话也多，请见谅！<br /></font>
<img src ="http://www.blogjava.net/zengke/aggbug/75371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zengke/" target="_blank">曾科</a> 2006-10-16 11:17 <a href="http://www.blogjava.net/zengke/articles/75371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>