occan

DOTNET学习

博客园 首页 新随笔 联系 订阅 管理
  8 Posts :: 0 Stories :: 2 Comments :: 0 Trackbacks

2006年4月13日 #

在大型数据库系统中,存储过程和触发器具有很重要的作用。无论是存储过程还是触发器,都是SQL 语句和流程控制语句的集合。就
本质而言,触发器也是一种存储过程。存储过程在运算时生成执行方式,所以,以后对其再运行时其执行速度很快。SQL Server 2000 不仅提供了用户自定义存储过程的功能,而且也提供了许多可作为工具使用的系统存储过程。

12.1.1 存储过程的概念
存储过程(Stored Procedure)是一组为了完成特定功能的SQL 语句集,经编译后存储在数据库。中用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

    在SQL Server 的系列版本中存储过程分为两类:系统提供的存储过程和用户自定义存储过程。系统过程主要存储在master 数据库中并以sp_为前缀,并且系统存储过程主要是从系统表中获取信息,从而为系统管理员管理SQL Server 提供支持。通过系统存储过程,MS SQL Server 中的许多管理性或信息性的活动(如了解数据库对象、数据库信息)都可以被顺利有效地完成。尽管这些系统存储过程被放在master 数据库中,但是仍可以在其它数据库中对其进行调用,在调用时不必在存储过程名前加上数据库名。而且当创建一个新数据库时,一些系统存储过程会在新数据库中被自动创建。用户自定义存储过程是由用户创建并能完成某一特定功能(如查询用户所需数据信息)的存储过程。在本章中所涉及到的存储过程主要是指用户自定义存储过程。

12.1.2 存储过程的优点
    当利用MS SQL Server 创建一个应用程序时,Transaction-SQL 是一种主要的编程语言。若运用Transaction-SQL 来进行编程,有两种方法。其一是,在本地存储Transaction- SQL 程序,并创建应用程序向SQL Server 发送命令来对结果进行处理。其二是,可以把部分用Transaction-SQL 编写的程序作为存储过程存储在SQL Server 中,并创建应用程序来调用存储过程,对数据结果进行处理存储过程能够通过接收参数向调用者返回结果集,结果集的格式由调用者确定;返回状态值给调用者,指明调用是成功或是失败;包括针对数据库的操作语句,并且可以在一个存储过程中调用另一存储过程。

    我们通常更偏爱于使用第二种方法,即在SQL Server 中使用存储过程而不是在客户计算机上调用Transaction-SQL 编写的一段程序,原因在于存储过程具有以下优点:

(1) 存储过程允许标准组件式编程
存储过程在被创建以后可以在程序中被多次调用,而不必重新编写该存储过程的SQL 语句。而且数据库专业人员可随时对存储过程进行修改,但对应用程序源代码毫无影响(因为应用程序源代码只包含存储过程的调用语句),从而极大地提高了程序的可移植性。

(2) 存储过程能够实现较快的执行速度
如果某一操作包含大量的Transaction-SQL 代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的,在首次运行一个存储过程时,查询优化器对其进行分析、优化,并给出最终被存在系统表中的执行计划。而批处理的Transaction- SQL 语句在每次运行时都要进行编译和优化,因此速度相对要慢一些。

(3) 存储过程能够减少网络流量
对于同一个针对数据数据库对象的操作(如查询、修改),如果这一操作所涉及到的 Transaction-SQL 语句被组织成一存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,否则将是多条SQL 语句,从而大大增加了网络流量,降低网络负载。

(4) 存储过程可被作为一种安全机制来充分利用
系统管理员通过对执行某一存储过程的权限进行限制,从而能够实现对相应的数据访问权限的限制,避免非授权用户对数据的访问,保证数据的安全。(我们将在14 章“SQLServer 的用户和安全性管理”中对存储过程的这一应用作更为清晰的介绍)

注意:存储过程虽然既有参数又有返回值,但是它与函数不同。存储过程的返回值只是指明执行是否成功,并且它不能像函数那样被直接调用,也就是在调用存储过程时,在存储过程名字前一定要有EXEC保留字
posted @ 2006-04-13 22:34 occan 阅读(34) 评论(0) 编辑

不知不觉,net伴我度过一年多时光了,回想起来,自己也走了不少的弯路。这里就写下我的一些给初学者(web开发)的建议,仅供参考。

1。html要先搞明白。

2。要多看看优秀的网站。

3。先了解。net的基本架构,花上一些时间看看有关的报道,多上MSDN去看看。

4。确定要学的语言,先了解个大致用途。我学的是C#(跟着时髦走,呵呵)。

5。学习数据库基本操作。可能的话,还是要看看数据结构之类的书为好。

6。正是进入语言学习(如c#),不求甚解,先把大致的功能都了解。

7。看看asp。net方面的资料,大致了解。懂得基本常识。

8。再次进入语言学习,这次要60%的掌握。有了这个基础,就能进入基本的asp。net操作。

9。进入asp。net学习,已经可以进行基本的web开发了,也算入门了。

10。学习web开发要用到的一些辅助知识(如css,js等)

11。没了,找个项目自己学着做,不会了,就查资料,学什么都要有个过程,不可过急。
posted @ 2006-04-13 22:31 occan 阅读(79) 评论(0) 编辑

虽然大概一两年前我还在夸夸其谈桌面应用程序是将来的潮流,大学生们现在还是偶尔向我请教职业发展的问题。所以我把我的建议写下来。以供学生们阅读,嘲笑,忽略。

大多数锐气十足的学生从来不向前辈征求意见。在计算机科学领域,这样做是正确的。因为前辈们很可能说些“在2010年前,市场对于那些只会敲击键盘的代码工人的需求将会超过一亿(因此前景是乐观的)”,或者诸如“Lisp语言现在真的很热门”。

我和那些前辈也差不多,当我给别人建议时,实际上我不知道自己在说些什么。我是如此的落后于时尚,以至于连AIM也搞不明白,而不得不使用 email(恐龙时代的产品,在那个时代,音乐是刻在扁扁的的圆圆的盒子上,噢,那种盒子叫cd)。(译者按:我认为祖儿这里在说反话,后文很多地方作者都在说反话,读者尽量理解这种美国式幽默吧。)

所以你最好不要理睬我将要说的,你应该立刻去制作某种在线交友软件。

然而,

如果你喜欢编程,那就感谢上帝吧:你属于幸运的少数人,这些人喜欢工作,他们的工作可以保证他们能过上舒适的生活。大多数人没有这么幸运。对大多数人来说,工作是不愉快的,忍受工作的目的攒钱,是为了在年满65岁退休后能过上自己想过的生活。如果他们想过的生活不需要灵活的膝盖,明亮的眼镜,轻盈的脚步的话。

现在让我回到主题,我将提供一些建议。

好了,不罗嗦了,下面就是Joel给计算机系学生们七条免费的建议:

毕业前学会写作
毕业前学会C语言
毕业前学习微观经济学(microeconomics)
不要因为某些非计算机课程枯燥无趣就敬而远之
学习有大量编程实践的课程
不要担心工作都跑到印度去了
好好做夏季毕业实习
让我逐条解释这些建议。但解释之前我要说明一下,如果因为这些建议是Joel的建议你就打算无条件地接受,以至于连我的理由都想跳过,那么你就太单纯,太容易被别人骗了。如果你是那种单纯的人,我还要给你第八条建议,找心理医生咨询一下如何培养自信(self-esteem)。

毕业前学会写作

如果Linus Torvalds不懂如何布道的话,Linux会成功吗? 正象每一个黑客,Linus精通写作,他知道如何准确地在email和邮件讨论组中使用书面英语表达自己的思想,所以他能够从全世界召集大量志愿者为Linux工作。

你听说过最近风靡全世界的极限编程(Extreme Programming)吗? 即使你不懂什么是极限编程,你至少听说过这个词。为什么?因为宣传极限编程的人都是天才的作者和演说家。

就看看你身边的那些小型的软件开发组织吧,最有权力和影响力的人是那些可以用自信,准确,舒适的英语交流的人。好吧,我承认这些人也许言过其实,但是你无可奈何。

一个合格的程序员和一个伟大的程序员的区别不在于知道多少种编程语言,不在于他们是喜欢Python或者Java,而是在于他们是否擅长表达。他们能够说服,所以他们获得权力。他们能够写清楚明白的评论和接口文档,所以他们使得别人不用重写,而可以重用他们的代码,否则他们的代码就是毫无用处的。他们也能够写出清晰的用户手册,于是最终用户可以理解他们的代码是做什么用的,明白了他们的工作的价值。sourceforge埋葬着许多精美的代码,这些已死的代码无人使用,因为代码的作者很少写(或者根本不写)用户手册。

我不会雇佣一个不懂写作的程序员。如果你擅长写,你就很容易找到工作,紧接着你就会被要求写技术规格文档,这意味着你已经被管理层注意到了。

大学里有一些课程,要求你做很多的写作练习,不要犹豫,赶快参加这些课程。不要错过任何要求你每周或者每天练习写作的课程。

给自己建立一个网络日志(weblog)。在上面写的越多,你会写地越容易。写地越容易,你就写地越多,这是一个正向地循环激励。

毕业前学会C语言
我可没有说是C++。虽然现在用C的工作不多,但是掌握各种编程语言的程序员事实上用C来交流(lingua franca);更重要的是,C比某些“现代”语言更接近机器语言。我不管现在大学里在教什么流行的垃圾语言(trendy junk),你至少得花一个学期接近机器。否则,你不可能使用高级语言写出高效的代码。这意味这你不会有机会写编译器或者操作系统,也许这是更好的编程工作;别人不会相信你能够为大项目设计架构。无论你知道多少高级的控制结构,知道如何进行错误处理,如果你不能解释为什么while (*s++ = *t++);的意思是进行字符串拷贝(而且对你而言这是世界上最自然,最易懂的代码),那么你就是在对编程一窍不通的状态下编程(programming based on superstition)。打个比方,就好比一个医生不懂基本的解剖学就给你开处方,如果你问这个医生为什么开这种药而不是那种药,他会说因为医药销售代表说这种药有用。

毕业前学习微观经济学(microeconomics)

我个人对经济学的一些理解:在经济学刚诞生的时候,它只是局限于有限的领域,在这些领域中人们发展和发现了很多有用的理论和很有趣的事实,这些理论和事实是从逻辑上是可以证明的。然后, 经济学开始走下坡路了。 “有限的领域”就是微观经济学,它对于商业可以进行有意义的指导。然后,事情就开始变糟了(以下部分你可以跳过),你接下来碰到的是讨论诸如失业率和银行利率之间关系之类东东的宏观经济学,很多时候宏观经济学讨论的理论都是无法证明正确或者错误的。接下来事态更加恶化了,经济学中的一些领域开始和物理学搭界,嗯,学习物理经济学也许你帮你在华尔街找到好工作。言归正传,无论如何请学习微观经济学,因为你需要知道什么是“供给和需求”,什么是竞争优势,什么是净现值(NPVs,Net Present Value,指项目经济寿命期内现金流入总和与现金流出总和之差额),什么是折扣和边际效用(discounting and marginal utility),如果你真想了解商业是如何运作的话。

为什么计算机系的学生要学习经济学?因为理解商业基本规律的程序员对商业界来说是宝贵的程序员。我记得无数个程序员使我非常沮丧,因为他们在代码中坚持某些疯狂的设计,这些设计从技术上来说,完美;从资本主义的角度来看,发疯。如果你是一个理解商业的程序员,商业会给你回报。这就是你要学习经济学的原因。

不要因为某些非计算机课程枯燥无趣就敬而远之

首先,你需要让你的学分平均分(GPA)看起来漂亮点。

不要低估学分平均分的威力。很多雇主和人事经理(包括我)阅读简历时首先看成绩,为什么?因为这代表了大部分的教授在很长的时期内对你的学业的一个平均的看法。托福成绩(美国的托福大致相对于我国的高考中的语文考试)?哈,几个小时的测验而已。当然学分不一定说明了一切,如果你修的是很难的课程,学分就有可能低一点。即使你的学分平均分很高,我还是要看各科分数是否一致。如果你应聘的是软件工程师职位,我为什么要关心你在大学里学的欧洲历史课程分数的高低呢?毕竟,历史很枯燥。那么要是你要编程的部分也是很枯燥的,你是不是要放弃了?事实上,有时候编程是枯燥的,如果你不能忍受编程中的枯燥部分的话,你就不能完成整个工作,雇主不愿意雇佣你这样的员工。

我在大学里修过一门叫做“文化人类学”的课程,因为那时候我也搞不懂我到底要学什么,听起来这么课程可能还蛮有意思的。

出乎我的意料。我不得不阅读大量讲述巴西热带雨林中的印第安人如何如何的书,让人真昏昏欲睡。听老师讲解也好不到哪去,我发觉看教室外的草如何长更有趣点。土著人如何烤蕃薯藤和我有什么关系?我为什么要去讨论如何烤蕃薯藤?但是期中考试马上就要到了,我暗暗下定决心,如果我能跨越“文化人类学”这个障碍,以后也许没有什么能难倒我了。我决心得A并且得到了A。以后当我不得不坐在林肯中心,连看18个小时的瓦格纳的《尼伯龙根的指环》时,我终于明白我为什么要学习“文化人类学”了,相比之下,我也能忍受这种歌剧了。

学习有大量编程实践的课程

我还记得决定不去读研究生的那一刻。

就是在学习《动态逻辑》(Dynamic Logic)这门课的时候,我记得是耶鲁的Lenore Zuck(一个天才的教师)教的。

修这门课的时候,我已经不再是雄心勃勃了。我可不指望在这么课程中得个A,我梦想的是混个及格。逻辑本质上是很简单的:如果结论正确,前提必须正确。例如,如果“所有读书好的人都能找到工作”并且“张三的读书好”,那么“张三能够找到好工作”。就这么简单。

但是我要学的是动态逻辑, 动态逻辑和一般逻辑差不多,但是要考虑时间因素。例如,“在你开灯之后,你可以看见你的鞋子”加上“过去灯被打开了”意味着“你现在可以看到你的鞋子”

动态逻辑学对于象Zuck教授这样的天才理论家来说非常诱人,因为这门学科的知识也许可以用来证明计算机程序是否正确。我记得在第一堂课上,为了证明“如果你有一盏关着的灯”并且“你按了一下开关”,那么“现在灯亮了”,Zuck教授就使用了两黑板加上边上的墙壁。

证明过程难以置信的复杂。我觉得如此复杂的证明过程很可能会有小错误,但是我没办法证明证明过程本身是正确的。事实上,写在黑板上的证明跳过了很多中间步骤,许多步的证明使用了演绎法,使用了归纳法,以及一些研究生才懂的证明方法。

作为课后作业,我们需要证明以下命题:如果灯过去是关着的,并且现在它是开着的,请证明有人按了开关

我真的试着证明它了。

我花了许多小时,试图证明这个命题。

在无数个小时的努力后,我发觉Zuck博士的原始的证明有一个逻辑上的错误,也许这个错误是我的笔记抄错了,我不知道。于是我终于认识到,如果为了证明一个简单的问题需要花三个小时写下几黑板的证明步骤,再考虑到这个漫长的证明过程中可能会引入种种错误,那么这种机制是不可能用来证明任何有趣的东西的。

对动态逻辑学家来说,有用是无关紧要的。

于是我退出了那门课程,发誓永远不会去读计算机系的研究生。

这个故事的主题是,计算机科学和软件开发不一样。如果你非常非常幸运,你的学校会开软件开发的课程。然而,他们也可能不开这样的课程,因为名牌大学认为教授实用技巧的事情应该留给那些二三流的技术学院或者某些释放犯人再安置计划。你可以在任何地方学习编程,我们是耶鲁大学,我们培养未来的世界领导人。你付给耶鲁16万美元的学费就是为了学习如何写循环语句吗?你把耶鲁当成什么地方了?Java速成班吗?哼。

问题在于,我们没有一个专业的学校教授软件开发。所以如果你想成为一个程序员,你可以进计算机系读书(当然计算机科学也值得学习),但是你学的不是软件开发。

如果走运的话,你可以在计算机系发掘出很多有大量编程实践的课程,就象你能在历史系找到很多提供写作水平的课程一样。这些课程绝对值得学习。如果你喜欢编程,不要为你不能上教授诸如lambda算子或者线性代数的课程沮丧,在那里你连摸一下计算机的机会都没有。找找看有没有名字中带有“实习(Practicum)”字样的课程,不要在乎Practicum是个拉丁语。有用的(无奈状)课程就是需要在课程名中塞一些拉丁语,才能从那些装模作样(Liberal Artsy Fartsy)管理层的眼前蒙混过关。

不要担心工作都跑到印度去了

啊哈,如果你人在印度,你就无所谓了。愿你享受外包带来的工作机会并顺祝身体健康。

但是我听说现在愿意读计算机系的学生越来越少了。据说原因之一是工作机会都跑到印度去了。我认为这种观点是大错特错。首先,根据眼前的商业时尚选择事业是非常愚蠢的。其次,即使工作真的都跑到印度和中国去了,编程对于其他有趣的工作来说都是极好的训练,例如业务流程工程(business process engineering)。第三,无论是在美国还是印度,好程序员仍然是非常短缺的,请相信我。当然,现在有许多所谓搞IT的人吵吵嚷嚷地说就业形势不好,工作太难找。但是事实如何?恕我直言,好程序员找工作还是很容易。第四,你还有更好的主意吗?历史系的毕业生找工作更容易吗?去法学院如何?据我所知,99%的律师恨他们的工作,每分钟都恨。而且律师一周工作90小时。正象我以前说过的,如果你喜欢计算机,那么感谢上帝,你将属于全世界人中的极少数的幸运儿,这些幸运儿热爱他们的工作,而且工作也可以提供体面的收入。

实际上,我也不认为报考计算机系的人越来越少有多大的意义。相对于internet泡沫时期大家都疯狂的往计算机系挤,现在的人数回落只是回归正常水平而已。在泡沫时期,我们这个行业涌入了许多对计算机毫无兴趣的南郭先生,他们梦想的是拿着高的吓人的薪水加诱人的期权,然后年轻退休。谢天谢地,现在这些人都跑了。

好好做夏季毕业实习

明智的招聘者知道热爱编程的人初中就为当地的牙医写数据库程序,高中就在计算机夏令营教课,为校报规划网站,在某个软件公司做实习。他们找的就是这样的人。

如果你喜欢编程,你最容易犯的最大的错误就是“有活就接”。我知道,其他专业的学生假期打工可顾不了这些条条框框。但是你不一样,你拥有一种特殊技能,不要浪费它。当你毕业时,你的简历上应该已经罗列一堆的编程工作实习。让其他人去“为大家提供租车服务”(Tom Welling是个例外,他业余时间去演超人)。

最后,为了让你的生活更容易一点,也为了说明我这篇文章是能够自圆其说的,我将给我自己的公司的做做广告。我的公司Fog Creek软件公司,可以为大学生提供软件开发方面的实习机会。在我们公司,你可以学习“编码,开发,商业”。去年在我们公司实习的Ben就是这么说的,可不是因为我给他什么好处他才这么说。二月一号截至,抓紧机会吧。

如果你听了我的建议,你就会太早地卖掉Microsoft公司的股票,拒绝Google提供的职位,原因是因为你已经拥有自己的公司了。到时候可别后悔,更别怪我,呵呵。

posted @ 2006-04-13 22:30 occan 阅读(51) 评论(0) 编辑

我们已经知道,ASP.NET 中使用 ADO.NET 访问数据库,通过 OleDb 的连接可以访问 Access 数据库——我们非常常用的低端数据库之一。本文讨论了 ASP.NET 中可能看到的若干错误提示,从中看到 Access 2000 和 Access XP 创建的数据库文件,在访问出现错误时会出现不太相同的错误提示。希望对大家有所帮助。另一个要点是,希望通过此文,使大家对 ASP.NET 中 Access 数据库文件的 NTFS 权限设置有所新的认识。
(一)实验过程 

为了叙述方便,举个具体例子做个实验:应用程序为 /test ,数据库存放在 D:\wwwroot\test\data\db1.mdb,我们已经知道在 ASP.NET 中是以一个叫做 ASPNET 虚拟用户的身份访问数据库的,我们需要给这个账户以特定的 NTFS 权限才能使 ASP.NET 程序正常运行。 


为了得到最严格的 NTFS 权限设置,实验开始时我们给程序最低的 NTFS 权限: 

  a) D:\wwwroot\test\data\ 文件夹的给用户ASPNET以如下权限: 

 允许 拒绝 
完全控制 □ □ 
修改 □ □ 
读取及运行 √ □ 
列出文件夹目录 √ □ 
读取 √ □ 
写入 □ □ 

 

   b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限: 
      √ 允许将来自父系的可继承权限传播给该对象 

 

1.1  对于某个只包含有"SELECT"命令的aspx程序,上述权限设置运行时无障碍,即:上述权限已经满足这类程序的运行了。 


1.2  对于包含有"UPDATE""INSERT""UPDATE"等命令的aspx程序, 

(a) 如果 db1.mdb 是 Access 2000 创建的数据库,出现如下错误: 

"/test"应用程序中的服务器错误。 
--------------------------------------- 
Microsoft Jet 数据库引擎打不开文件'D:\wwwroot\test\data\'。 它已经被别的用户以独占方式打开,或没有查看数据的权限。  
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。  
异常详细信息: System.Data.OleDb.OleDbException: Microsoft Jet 数据库引擎打不开文件'D:\wwwroot\test\data\'。 它已经被别的用户以独占方式打开,或没有查看数据的权限。 


(b) 如果 db1.mdb 是 Access XP 创建的数据库,出现如下错误: 

"/test"应用程序中的服务器错误。 
---------------------------------------------- 
操作必须使用一个可更新的查询。 
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。  
异常详细信息: System.Data.OleDb.OleDbException: 操作必须使用一个可更新的查询。 

 

(c) 原因初步分析:因为包含有"UPDATE""INSERT""UPDATE"等命令,需要对数据库文件本身进行写入操作,所以上述权限不能满足此需求,我们需要进一步放开权限。 

我们放开一些权限, 
  a) D:\wwwroot\test\data\ 文件夹不变: 

   b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:   允许 拒绝 
完全控制 □ □ 
修改 □ □ 
读取及运行 √ □ 
列出文件夹目录 √ □ 
读取 √ □ 
写入 √ □ 

 

1.3  放开权限后继续实验, 

(a) 如果 db1.mdb 是 Access 2000 创建的数据库,出现如下错误: 

"/test"应用程序中的服务器错误。 
------------------------------------------ 
不能锁定文件。 
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。  
异常详细信息: System.Data.OleDb.OleDbException: 不能锁定文件。 

 

(b) 如果 db1.mdb 是 Access XP 创建的数据库,没有出现错误。 

 

(c) 原因初步分析:我们发现在打开 Access 数据库时,同时会在所在目录生成一个同名的 *.ldb 文件,这是一个 Access 的锁定标记。鉴于此,我们猜测,用户 ASPNET 访问 Access 数据库时,也需要生成一个锁定标记,而该目录没有允许其写入,因此出错。至于 Access XP 创建的数据库为什么没有这个错误,原因还不得而知。 

我们进一步放开权限, 
  a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以如下权限:  允许 拒绝 
完全控制 □ □ 
修改 □ □ 
读取及运行 √ □ 
列出文件夹目录 √ □ 
读取 √ □ 
写入 √ □ 


   b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限: 
      √ 允许将来自父系的可继承权限传播给该对象 


1.4 继续实验,发现错误已解决,那么上面这个权限就是我们需要放开的"最低权限"。 

(a) 如果 db1.mdb 是 Access 2000 创建的数据库,我们会发现一个小问题:生成的 *.ldb 文件不会自己删除,访问后该文件依然存在,但这个问题不会影响 ASP.NET 的正常运行。 

(b) 如果 db1.mdb 是 Access XP 创建的数据库,没有出现上面类似问题。 

(c) 原因初步分析:我们仅仅是给了 ASPNET 以写入文件夹的权限,没有给它修改的权限,所以文件一旦写入,便无法修改其内容,*.ldb 也就删除不掉了。 


如果非要解决这个问题,进一步放开权限为: 
  a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以如下权限:  允许 拒绝 
完全控制 □ □ 
修改 √ □ 
读取及运行 √ □ 
列出文件夹目录 √ □ 
读取 √ □ 
写入 √ □ 


   b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限: 
      √ 允许将来自父系的可继承权限传播给该对象 


1.5  附带着,实验另一种情形:我们把 db1.mdb 在 Access 打开编辑,同时访问 ASP.NET。 

(a) 如果 db1.mdb 是 Access 2000 创建的数据库,我们发现并没有出现什么问题。 


(b) 如果 db1.mdb 是 Access XP 创建的数据库,出现如下错误: 

"/zhao"应用程序中的服务器错误。 
------------------------------------------------ 
不能使用 '';文件已在使用中。 
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。  
异常详细信息: System.Data.OleDb.OleDbException: 不能使用 '';文件已在使用中。 


(c) 原因初步分析:Access 数据库是单用户单线程的数据库,我们在 Access 里面打开编辑数据库文件时其实是以当前 Windows 用户(比如Administrator)身份打开数据库,而 ASP.NET 默认使用的是 ASPNET 虚拟用户(隶属于 Users 组),级别低于 Administrator,无法和 Administrator "抢夺"权限,所以出现冲突错误。至于 Access 2000 忽略这个问题的情形我们也不必做讨论了,可能是 Access 2000 没有考虑那么多因素吧。 

1.6  再附带一种情形:将 db1.mdb 的属性改为"只读",无论是 Access 2000 还是 Access XP 都将分别出现与 1.2 中各自的错误相同的错误提示。 

(二)实验结论 

1. 我们首先再次总结一下 Access 数据库文件的 NTFS 权限设置的缘起: 

   在 ASP.NET 中默认是以一个叫做 ASPNET 的虚拟用户的身份来访问、操作数据库的,你可以在"控制面板"-"管理工具"-"计算机管理"-"本地用户和组"-"用户"中看到这个用户,默认情况下是: 

      全名:ASP.NET 计算机帐户 
      描述为:用于运行 ASP.NET 辅助进程(aspnet_wp.exe)的帐户。 
      隶属于:Users组。 

   使用这么一个隶属于 Users 组的用户来进行文件操作、数据库操作的风险是要比用一个 Administrators 组的用户的风险要小得多,这也是 ASP.NET 在安全方面的一个考虑吧。 

   既然是这么一个用户需要访问、操作数据库文件本身,那么我们就需要给它一定的 NTFS 权限以允许它的访问。显然没有 NTFS 的权限许可,ASPNET 就无法访问、操作数据库,就会出现上面实验中所看到的那些错误了。 


2. 经过上面的实验,我们已经知道如下的 NTFS 权限设置是可以满足一般需求的: 

  a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以如下权限:  允许 拒绝 
完全控制 □ □ 
修改 □ □ 
读取及运行 √ □ 
列出文件夹目录 √ □ 
读取 √ □ 
写入 √ □ 


   b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限: 
      √ 允许将来自父系的可继承权限传播给该对象 


同时我们也注意到 db1.mdb 是否为"只读"文件对 ASPNET 的访问也会有一定影响。 


3. 上述权限设置可以直接设置给 ASPNET 用户自己,也可以设置给 Users 组,或者直接给 Everyone 组上述权限都是可以的。因为 ASPNET 隶属于 Users 组,可以通过 用户组 给 ASPNET 设置权限。 


4. NTFS 权限在文件或文件夹右击后得到的"属性"对话框-"安全"选项卡中设置,一般情况下,可以考虑给 Adminitrators 组以"完全控制"的权限,同时不要轻易在"拒绝"中打勾,有关 NTFS 权限设置的技巧,可以咨询网络管理员、网络安全专家的建议。 

注:FAT, FAT32 格式的分区中不支持 NTFS 权限。 

5. Windows 2000 系列,Windows Server 2003 系列的"安全"选项卡默认是很容易找到的,但 Windows XP Professional 中的"安全"选项卡默认是关闭的,可以将"控制面板"-"文件夹选项"-"查看"选项卡中的"高级设置"中"使用简单共享(推荐)"一项的"√"去除,"确定"之后,再次按照上面的方法即可看到"安全"选项卡了。 

posted @ 2006-04-13 22:28 occan 阅读(122) 评论(0) 编辑

一、认识Web.config文件
  Web.config文件是一个XML文本文件,它用来储存 ASP.NET Web 应用程序的配置信息(如最常用的设置ASP.NET Web 应用程序的身份验证方式),它可以出现在应用程序的每一个目录中。当你通过VB.NET新建一个Web应用程序后,默认情况下会在根目录自动创建一个默认的
Web.config文件,包括默认的配置设置,所有的子目录都继承它的配置设置。如果你想修改子目录的配置设置,你可以在该子目录下新建一个Web.config文件。它可以提供除从父目录继承的配置信息以外的配置信息,也可以重写或修改父目录中定义的设置。

  在运行时对Web.config文件的修改不需要重启服务就可以生效(注:<processModel> 节例外)。当然Web.config文件是可以扩展的。你可以自定义新配置参数并编写配置节处理程序以对它们进行处理。

  二、web.config配置文件(默认的配置设置)以下所有的代码都应该位于

<configuration>
<system.web>

  和

</system.web>
</configuration>

  之间,出于学习的目的下面的示例都省略了这段XML标记

  1、<authentication> 节

  作用:配置 ASP.NET 身份验证支持(为Windows、Forms、PassPort、None四种)。该元素只能在计算机、站点或应用程序级别声明。<authentication> 元素必需与<authorization> 节配合使用。

  示例:

  以下示例为基于窗体(Forms)的身份验证配置站点,当没有登陆的用户访问需要身份验证的网页,网页自动跳转到登陆网页。

<authentication mode="Forms" >
<forms loginUrl="logon.aspx" name=".FormsAuthCookie"/>

</authentication>

  其中元素loginUrl表示登陆网页的名称,name表示Cookie名称

  2、<authorization> 节

  作用:控制对 URL 资源的客户端访问(如允许匿名用户访问)。此元素可以在任何级别(计算机、站点、应用程序、子目录或页)上声明。必需与<authentication> 节配合使用。

  示例:以下示例禁止匿名用户的访问

<authorization>
 <deny users="?"/>
</authorization>

  注:你可以使用user.identity.name来获取已经过验证的当前的用户名;可以使用
web.Security.FormsAuthentication.RedirectFromLoginPage方法将已验证的用户重定向到用户刚才请求的页面.具体的实例请参考:

  Forms验证 http://www.fanvb.net/websample/dataauth.aspx

  3、<compilation>节

  作用:配置 ASP.NET 使用的所有编译设置。默认的debug属性为“True”.在程序编译完成交付使用之后应将其设为True(Web.config文件中有详细说明,此处省略示例)

  4、<customErrors>

  作用:为 ASP.NET 应用程序提供有关自定义错误信息的信息。它不适用于 XML Web services 中发生的错误。

  示例:当发生错误时,将网页跳转到自定义的错误页面。

<customErrors defaultRedirect="ErrorPage.aspx" mode="RemoteOnly">
</customErrors>

  其中元素defaultRedirect表示自定义的错误网页的名称。mode元素表示:对不在本地 Web 服务器上运行的用户显示自定义(友好的)信息。

  5、<httpRuntime>节

  作用:配置 ASP.NET HTTP 运行库设置。该节可以在计算机、站点、应用程序和子目录级别声明。

  示例:控制用户上传文件最大为4M,最长时间为60秒,最多请求数为100

<httpRuntime maxRequestLength="4096" executionTimeout="60" appRequestQueueLimit="100"/>

  6、 <pages>

  作用:标识特定于页的配置设置(如是否启用会话状态、视图状态,是否检测用户的输入等)。<pages>可以在计算机、站点、应用程序和子目录级别声明。

  示例:不检测用户在浏览器输入的内容中是否存在潜在的危险数据(注:该项默认是检测,如果你使用了不检测,一要对用户的输入进行编码或验证),在从客户端回发页时将检查加密的视图状态,以验证视图状态是否已在客户端被篡改。(注:该项默认是不验证)

<pages buffer="true" enableViewStateMac="true" validateRequest="false"/>

  7、<sessionState>

  作用:为当前应用程序配置会话状态设置(如设置是否启用会话状态,会话状态保存位置)。

  示例:

<sessionState mode="InProc" cookieless="true" timeout="20"/>
</sessionState>

  注:

  mode="InProc"表示:在本地储存会话状态(你也可以选择储存在远程服务器或SAL服务器中或不启用会话状态)

  cookieless="true"表示:如果用户浏览器不支持Cookie时启用会话状态(默认为False)

  timeout="20"表示:会话可以处于空闲状态的分钟数

  8、<trace>

  作用:配置 ASP.NET 跟踪服务,主要用来程序测试判断哪里出错。

  示例:以下为Web.config中的默认配置:

<trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true" />

  注:

  enabled="false"表示不启用跟踪;requestLimit="10"表示指定在服务器上存储的跟踪请求的数目

  pageOutput="false"表示只能通过跟踪实用工具访问跟踪输出;

  traceMode="SortByTime"表示以处理跟踪的顺序来显示跟踪信息

  localOnly="true" 表示跟踪查看器 (trace.axd) 只用于宿主 Web 服务器

  三、自定义Web.config文件配置节

  自定义Web.config文件配置节过程分为两步。

  一是在在配置文件顶部 <configSections> 和 </configSections>标记之间声明配置节的名称和处理该节中配置数据的 .NET Framework 类的名称。

  二是在 <configSections> 区域之后为声明的节做实际的配置设置。

  示例:创建一个节存储数据库连接字符串

<configuration>
 <configSections>
 <section name="appSettings" type="System.Configuration.NameValueFileSectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</configSections>

 <appSettings>
  <add key="scon" value="server=a;database=northwind;uid=sa;pwd=123"/>
 </appSettings>

 <system.web>
  ......
 </system.web>
</configuration>  

  四、访问Web.config文件

  你可以通过使用ConfigurationSettings.AppSettings 静态字符串集合来访问 Web.config 文件示例:获取上面例子中建立的连接字符串。

Dim sconstr As String = ConfigurationSettings.AppSettings("SconStr")
Dim scon = New SqlConnection(sconstr)

posted @ 2006-04-13 22:26 occan 阅读(59) 评论(0) 编辑

1) 不会英语:CS源于美国,重量级的文档都是英文的。不会英语,那么你只能忍受拙劣的翻译和大延迟的文档(翻译出来的文档几乎都是很久以前出版的东西)。

2) 急于求成:什么都没学习就开始编程是最大的忌讳。写C++程序语法都能错,数据结构连线性表都不知道,数据库不知道关系模型,TCP编程不知道socket,还是先坐下来学习几年再说(如果说工作急需,我只能说:早干嘛去了)

3) 过于好问:勤学好问是一种很好的品质,但是如果把勤学丢了,只留下好问,就是一个恶劣的素质了。事无巨细都去请教别人,一则会让人厌烦,二则由于没有系统学习过程,也是不可能学习好的。

4) 只会艳羡别人和说别人不该拿那么多钱,而自己却收入微薄:老实说,绝大多数情况下,收入的高低和你的水平是有正相关关系的。不是否认有关系的存在,但是绝对不会10个人中9个人有关系而独独你没有。少抱怨一些多学习一些,提升自己才是最重要的。

5) 过于不求甚解和过于求甚解。了解为什么是很重要的,但是要学习的东西很多,如果什么都弄明白,那么估计头发白了还没有找到所有答案。当然如果什么都不想细致了解,那么只能去做蓝领了。

6) 过分崇拜他人:我想信很多人都是很厉害的,值得大家崇拜,但是如果过于崇拜,把他们的话当成圣经就没有必要了。你需要突破他们,而不是崇拜他们。

7) 不想吃苦:IT业高收入和高竞争是联系在一起的。没有付出永远别想进步。
posted @ 2006-04-13 22:23 occan 阅读(89) 评论(0) 编辑

 


  在.NET中获取一台电脑名,IP地址及当前用户名是非常简单,以下是我常用的几种方法,如果大家还有其他好的方法,可以回复一起整理:
  
  1. 在ASP.NET中专用属性:
  
  获取服务器电脑名:Page.Server.ManchineName
  
  获取用户信息:Page.User
  
  获取客户端电脑名:Page.Request.UserHostName
  
  获取客户端电脑IP:Page.Request.UserHostAddress
  
  2. 在网络编程中的通用方法:
  
  获取当前电脑名:static System.Net.Dns.GetHostName()
  
  根据电脑名取出全部IP地址:static System.Net.Dns.Resolve(电脑名).AddressList
  
  也可根据IP地址取出电脑名:static System.Net.Dns.Resolve(IP地址).HostName
  
  3. 系统环境类的通用属性:
  
  当前电脑名:static System.Environment.MachineName
  
  当前电脑所属网域:static System.Environment.UserDomainName
  
  当前电脑用户:static System.Environment.UserName
  
  举例子来说明:
  
  using System.Net;
  private void ButtonIP_Click(object sender, System.EventArgs e)
  {
  System.Net.IPAddress[] addressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;
  if (addressList.Length>1)
  {
  TextLIP.Text = addressList[0].ToString();
  TextSIP.Text = addressList[1].ToString();
  }
  else
  {
  TextLIP.Text = addressList[0].ToString();
  TextSIP.Text = "没有可用的连接";
  }
  }
posted @ 2006-04-13 22:22 occan 阅读(70) 评论(0) 编辑

冒泡排序

   学语言要花大力气学数据结构和算法。

using System;

namespace BubbleSorter
{
public class BubbleSorter
{
public void Sort(int [] list)
{
int i,j,temp;
bool done=false;
j=1;
while((j<list.Length)&&(!done))
{
done=true;
for(i=0;i<list.Length-j;i++)
{
if(list[i]>list[i+1])
{
done=false;
temp=list[i];
list[i]=list[i+1];
list[i+1]=temp;
}
}
j++;
}

}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,13,6,10,55,99,2,87,12,34,75,33,47};
BubbleSorter sh=new BubbleSorter();
sh.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0} ",iArrary[m]);
Console.WriteLine();
}
}
}


选择排序

  本人用了C#开发出选择排序算法。希望能为C#语言的学习者带来一些益处。不要忘了,学语言要花大力气学数据结构和算法。

using System;

namespace SelectionSorter
{
public class SelectionSorter
{
private int min;
public void Sort(int [] list)
{
for(int i=0;i<list.Length-1;i++)
{
min=i;
for(int j=i+1;j<list.Length;j++)
{
if(list[j]<list[min])
min=j;
}
int t=list[min];
list[min]=list[i];
list[i]=t;
}

}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
SelectionSorter ss=new SelectionSorter();
ss.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0} ",iArrary[m]);
Console.WriteLine();

}
}
}

插入排序

  插入排序算法。对想提高C#语言编程能力的朋友,我们可以互相探讨一下。如:下面的程序,并没有实现多态,来,帮它实现一下。

using System;

namespace InsertionSorter
{
public class InsertionSorter
{
public void Sort(int [] list)
{
for(int i=1;i<list.Length;i++)
{
int t=list[i];
int j=i;
while((j>0)&&(list[j-1]>t))
{
list[j]=list[j-1];
--j;
}
list[j]=t;
}

}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,13,3,6,10,55,98,2,87,12,34,75,33,47};
InsertionSorter ii=new InsertionSorter();
ii.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0}",iArrary[m]);
Console.WriteLine();
}
}
}

希尔排序

   希尔排序是将组分段,进行插入排序. 对想提高C#语言编程能力的朋友,我们可以互相探讨一下。如:下面的程序,并没有实现多态,来,帮它实现一下。

using System;

namespace ShellSorter
{
public class ShellSorter
{
public void Sort(int [] list)
{
int inc;
for(inc=1;inc<=list.Length/9;inc=3*inc+1);
for(;inc>0;inc/=3)
{
for(int i=inc+1;i<=list.Length;i+=inc)
{
int t=list[i-1];
int j=i;
while((j>inc)&&(list[j-inc-1]>t))
{
list[j-1]=list[j-inc-1];
j-=inc;
}
list[j-1]=t;
}
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,13,6,10,55,99,2,87,12,34,75,33,47};
ShellSorter sh=new ShellSorter();
sh.Sort(iArrary);
for(int m=0;m<iArrary.Length;m++)
Console.Write("{0} ",iArrary[m]);
Console.WriteLine();
}
}
}

posted @ 2006-04-13 22:13 occan 阅读(1297) 评论(2) 编辑