[转载]整理了几条 LogParser 命令

mikel阅读(1132)

[转载]http://www.room702.cn/index.php/archives/244

注入分析:
LogParser "select time,c-ip,cs-uri-stem,cs-uri-query,sc-status,cs(User-Agent) from ex080228.log where cs-uri-query LIKE '%select%'"

查询日志文件:ex080228.log , 查询关键字:select

==================================================

反射型XSS分析:
LogParser "select time,c-ip,cs-uri-stem,cs-uri-query,sc-status,cs(User-Agent) from ex080228.log where cs-uri-query LIKE '%<script>%'"

查询日志文件:ex080228.log ,查询关键字:<script>

==================================================

特定时间记录搜索:
LogParser "select time,c-ip,cs-uri-stem,cs-uri-query,sc-status,cs(User-Agent) from ex080228.log where time between TIMESTAMP( '09:07:00', 'hh:mm:ss' ) and TIMESTAMP( '09:08:00', 'hh:mm:ss' )"

查询日志文件:ex080228.log ,搜索时间段:09:07:00 至 09:08:00

==================================================

根据IP地址统计访问情况:
LogParser "select date,time,c-ip,cs-uri-stem,cs-uri-query,cs(User-Agent),sc-status from ex080228.log WHERE IPV4_TO_INT(c-ip) BETWEEN IPV4_TO_INT('172.16.9.0') AND IPV4_TO_INT('172.16.9.255')" 

查询日志文件:ex080228.log , 搜索IP段:172.16.9.0/24

==================================================

目录猜解搜索:
LogParser "select time,c-ip,count(time) as BAD from ex080228.log where sc-status=404 group by time,c-ip having BAD>5"

查询日志文件:ex080228.log , 搜索错误次数大于N次:5

==================================================

表单破解搜索:
LogParser "select time,c-ip,cs-uri-stem,count(time,cs-uri-stem) as BAD from ex090609.log where sc-status=200 and cs-method='POST' group by time,c-ip,cs-uri-stem having BAD>4"

查询日志文件:ex090609.log , 搜索同一秒内POST次数大于N次:4

==================================================

异常User-Agent搜索:
LogParser "select time,c-ip,cs-uri-stem,cs-uri-query,sc-status,cs(User-Agent) from ex080228.log where cs(User-Agent) NOT LIKE 'Mozilla%'"

查询日志文件:ex080228.log , 搜索User-Agent:全部未以Mozilla开头的User-Agent

==================================================

不正常的HTTP Method
LogParser "select time,c-ip,cs-method,cs-uri-stem from ex090609.log where cs-method in ('HEAD';'OPTIONS';'PUT';'MOVE';'COPY';'TRACE';'DELETE')"

查询日志文件:ex090609.log , 搜索异常方法:('HEAD';'OPTIONS';'PUT';'MOVE';'COPY';'TRACE';'DELETE')"



[转载]网站策划必备三大软件及介绍(一)

mikel阅读(1164)

[转载]网站策划必备三大软件及介绍(一) – 站长网 admin5.com.

一个网站项目立项以后,每个功能、页面的制作一般都会走这样一个流程:

项目策划(产品、功能策划及策划论证) 、界面设计与前期用户体验设计(ui+ue)、页面制作与前端脚本及后期用户体验设计、功能的程序编写与实现、功能测试、内容填充、全面检查与整站优化

我们可以发现,产品策划人员从开始一直到最后,都贯穿于整个项目的实施之中,而策划人员自己本身需要出具一些相关的图表或者文档,一般包括项目 结构图、功能流程图、页面框图、项目进度表以及对应的说明文档。这里我向大家推荐三个软件,一是Mindjet MindManager ,专门用于结构图制作,二是亿图,用于流程图制作,三是Axure,用于线框图制作,由于三者一起介绍篇幅太长,呵呵,分二部分到admin5来发。本文 就主要介绍Mindjet MindManager 与亿图(EdrawMax)。

这几个相关的图表与文档的制作中,说明文档我们可以用微软的word来实现,而项目结构图则可以使用Mindjet MindManager来实现,这个软件Mindjet MindManager 最新版本为V8.0,目前比较好用的是6.0汉化版。从字面上大家可以发现它有“思维引导管理”的意思,也就是使用此软件可以很方便的把自己的想法或者团 队的想法给充分的展现出来,经过最终的整理,将可以得到一个完整的结构图表。我们以vb86点com为例子,来看看一下Mindjet MindManager 的特点。我花几分钟制作出一张图表,见图1。

图1

这样一来,网站的结构就了然于胸了。也方便给其它流程的同事进行演示,此软件有几个特点:

a.每个节点都可以点击收缩或者伸展

b.可以导出常见的图片jpg、png、gif、bmp以及word、html等多种格式

c.可以在主文件中插入多个类似文档,实现不同文档之间的切换

d.支持各主题(方块)的局部对齐与全局对齐

e支持自定义样式等

Mindjet MindManager 的功能很多,如果大家有兴趣,可以去慢慢发掘。接下来我们来说一说流程图制作。

对于项目来说,有许多的流程,包括团队工作流程,项目的功能流程,用户体验流程等,我就从团队工作流程这一点来给大家介绍一下我常用的工具:亿 图(EdrawMax)。

此软件由上海风山网络科技有限公司出品,目前最版本是v5.0,准备推出。目前好用的版本是4.0版本。此软件包含了大量的图表例子,上手简 单。我们还用vb86团队工作流程作为例子,大家看一张表,见图2.

图2

我相信大家一定能制作出比我这个漂亮很多的图表来。

本软件有几个特点:

1、巨量的符号图库,可以满足你一切需求

2、可以导出多种格式,包括图形、文档格式、网页格式等

3、超多的例子,有许多只需要一改就能用

4、可以自定义多种主题风格,当然已经有很多主题提供了

5、图形之间支持吸附,很方便操作

6、标尺与辅助线非常好用,并有吸附功能

7、可自定义背景

8、可以自定义图片、符号、以及相关的几何参数等

总之,功能非常强大,制作流程图一流了。篇幅已经很长了,下一章我们再来介绍另一款常用工具:Axure线框图制作工具。

说明一下,www.vb86.com是我的小站,刚开两天,本文目的在于分享好用的策划工具(当然你也可以用来做很多东西),其次昵,也想在 admin5发一下链接,呵呵。感谢大家,欢迎一起分享你的好软件哦。

[转载]Javascript 通过json自动生成Dom小示例

mikel阅读(1158)

[转载]Javascript 通过json自动生成Dom小示例 – 花吻道 – 博客园.

json转html 三重奏

原料:json

var json={
‘div’:{id:’flower’,className:”a1″,sub:[
{
‘ul’:{id:’flower1′,className:[“a2″,”a3″],sub:[
{‘li’:{num:3,con:”内容内容内容”,fn:{‘click’:function(){alert(‘我是LiLi’)}}}}
]}
},
{
‘ul’:{id:’flower4′,className:[“a2″,”a3″],sub:[
{‘li’:{num:3,con:”第2轮了”,fn:{‘click’:function(){alert(‘我是LiLi’)}}}}
]}
},
{
‘span’:{id:’q’,con:”我是span”}
}
]}
}

id=id

className=class

num=循环次数

fn=绑定函数

con=元素内容

sub =代表有子节

主 菜:method

JsonToHtml={
init:function(data,parent){//jsonDB,父元素
for(var attr in data){
if(data[attr][id]){var num=1}else{var num=data[attr][num]||1}//如果存在id,则循环默认为1,因为id不可重复
for(var j=0;j<num;j++){
var obj= document.createElement(attr);
parent ? parent.appendChild(obj) : document.body.appendChild(obj);//递归时传入父元素,没有则默认从body输出
for(var attr2 in data[attr]){
var _tempAttr=data[attr][attr2];
switch(attr2){
case id:
obj.id=_tempAttr;
break;
case className: //支持多个class传入~简了点~
if(_tempAttr.length && _tempAttr.pop){
for(var k=0;k<_tempAttr.length;++k){
obj.className= obj.className+ +_tempAttr[k] ;
}
}else{ obj.className =_tempAttr;}
break;
case sub: //如果有子节点则开始递归
for(var i=0;i<_tempAttr.length;i++){
_tempAttr[i].sub ? this.init(_tempAttr[i]) : this.init(_tempAttr[i],obj)
}
break;
case con://设置内容,可以生成新的子元素
obj.innerHTML=_tempAttr;
break;
case num:
break;
case fn://绑定方法
for(var fns in _tempAttr){
if (window.addEventListener) {
obj.addEventListener(fns, _tempAttr[fns], false);
} else {
if (window.attachEvent) {
obj.attachEvent(on + fns, _tempAttr[fns]);
}
}
}
break;
default : //设置属性
obj.setAttribute(attr2,_tempAttr);break;
}
}
}
}
return this;
}
}

JsonToHtml.init(json); //初始化

上 菜

<div id=”flower” class=”a1″>
<ul id=”flower1″ class=”a2 a3″>
<li>内容内容内容</li>
<li>内容内容内容</li>
<li>内容内容内容</li>
</ul>
<ul id=”flower4″ class=”a2 a3″>
<li>第2轮了</li>
<li>第2轮了</li>
<li>第2轮了</li>
</ul>
<span id=”q”>我是span</span>
<div>

主 要还是通过递归和迭代来遍历json成员生成html元素 ,比较好的是num能制定循环次数可以少写很多代码.具体应用看场景了

这 只是个小例子,期待后续!

[原创]别让我猜!我是用户!

mikel阅读(1034)

大小站长一直在喊:”内容为王!“可真正又有多少人注重过用户体验才是网站的根本,即使内容再多,不能让访问者简单、轻松、快速的获得信息,再好的内容也只能埋没在”深巷“,现在已经是”酒香就怕巷子深“的时代了。
不妨各位站长扪心自问几个问题来测试一下自己的站的用户体验吧!
1.用户第一次访问你的网站,用户会不会知道这个网站是做什么的?
2.用户能明白各栏目的含义吗?
3.用户想找到感兴趣的信息需要几次操作?
4.注册用户会不会使用提供的功能?
5.用户不会用功能,是否提供了帮助说明?
这是我本人浏览网站时比较注意的几个问题,每个人可能浏览习惯不一样,可能对网站的体验评定标准不一样,但是如果上述几点不满足,相信大部分用户都不会第二次再访问你的网站了。
网站作为一种展示信息的媒体,不是做给自己看的,做站之前最好先考虑一下用户的感受,不要老盯着百度排行,再高的排名,给访问的人的感受很差,甚至是愤怒!相信你的站也只能是昙花一现,不要为做站而做站,既然做就踏踏实实的做个能让人浏览的站而不是蜘蛛浏览的站。

[转载]SqlServer性能优化——Slide Window

mikel阅读(1055)

[转载]SqlServer性能优化——Slide Window – smjack – 博客园.

虽然对数据库进行分区本身就能提高查询的性能,结合压缩,也能减少每次查询的IO。但如果数据持续增长,过于久远的历史数据就成了一个包袱,它们从 来不在查询结果中出现,却或多或少的影响着每次查询的时间,成了一个挥之不去的阴影。此外,由于一个分区表的分区是有上限的(在2005中这一上限是 1000),我们也并不能在一张表上一直分区下去。所以在这种情况下,我们一般需要同时拥有两张表,一张保存了最近的数据,用来应付所有 的查询,这张表要足够精简,在其上的查询要足够敏捷;同时有另一张表,保存所有过时的数据——我们并不能把过时的数据一删了事。

这里面的关键问题是,既然数据是随着时间持续增长的,那么当下有用的数据可能在几天后就过时了,那么怎样将这一部分过时的数据 从活动表迁移到存档表,而且要保证迁移过程的快速、平稳呢?如果采用常规的Select、Insert、Delete来进行数据迁移, 会有如下问题:

  1. IO过大,效率必然较低。
  2. 迁移过程表被锁住,所有查询都会被搁置。
  3. 恢复困难,如果想将移出的数据再移回来,需要进行同样的操作,IO和锁表的问题同样存在。

那么很容易 想到,利用之前提到的分区的Switch操作来解决迁移的问题,将整个分区而不是数据在活动表和存档表中迁移。由于 Switch的元数据操作属性,这一几乎没有什么IO的操作效率极高,而且也不会锁表。基于以上方法进行的周期性自动化的数据迁移,就是Slide Window的基础

原理图

假设我们已经有一张活动表,分了四个区,分别对应去年,今年一 月、二月以及三月以后的数据:

image

同时我们有另外一个存档表,分成了两个区, 第一个区对应今年以前的数据,另外一个分区的范围是今年之后:

image

注意,活动表的第一个分区存 档表中的第二个分区是没有数据的,这是进行Slide Window的前提条件

现在,我们考虑将活动表中的一月份 的数据放入存档表中,而且我们还要保证在迁移之后,两张表保持和迁移前相似的状态。

那么我们可以采用如下的步骤:

1. 在存档表中建立新分区:

image

2.将活动表的第二个分区挪到存档表的第二个分 区中:

image

迁移的结果如下:image

至此,我们已经完成了数据的迁移,但为了恢复两 张表到之前的状态,我们还需要以下两个步骤:

3.合并存档表的第一和第二个分区。

4.拆分活动表的第三个分区。

最后的结果,活动表:

image 存档表:

image我们可以看到迁移过后,两张表的分区数量没有变,而且存档表的第二个 分区依然是空的。当需要迁移二月份的数据时,我们可以采用和上面完全一样的步骤进行迁移。而这一过程,类似在时间轴上开了一个窗口,将当前数据在活动表上 展示,随着时间推移,窗口不断向前滑动(活动表的边界前移),而且窗口大小(活动表的分区数)始终保持不变,这就是Slide Window(滑动窗口)这一名称的来源。

建立存档表

建立存档表最简单的方法是选中分好区的活动表,在 Storage菜单中选择“Manage Partition”,然后选择“Create a stagin table for partition switching”。建议将“Staging table name”改成固定的没有数字后缀的名字,之后随便选择一个“Switch Parition”,最后生成创建存档表的脚本。

image

由于指定了待切换的分区,所以这里脚本中会添 加对应的约束,由于我们要创建的存档表并不应该有边界限定,所以应当把脚本中添加边界约束的部分删除,运行,生成存档表。

接下来要对存 档表进行分区,一般来说,存档表分成两个区就可以应对任意分区数量的活动表了,当然,分的更多也没有问题。存档表的分区边界要和活动表的对应边界一致,也 就是存档表的第一个分区和第二个分区的边界等于活动表的第一个分区和第二个分区的边界。

此时存档表中并没有数据,我们可以用

ALTER TABLE [STable] SWITCH PARTITION 1 TO [DTable] PARTITION 1

将活动表的第一个分区迁移到存档表的第一个分区中。这样活动表的第一个分区、存档表的第二个分区为空,也就达成了前文所述的执行Slide Window的前提条件。

自动执行

有了存档表,就可以进行滑动窗口了。以用时间类型字段做分区依据的表为例,这里我把执行脚本存到一个存储过程里:

CREATE PROCEDURE [dbo].[sp_SlideWindow] 
@SplitRange SMALLDATETIME -- 指定活动表新增分区的边界

AS
BEGIN
    DECLARE @SwitchRange SMALLDATETIME
    DECLARE @MergeRange SMALLDATETIME
    --获得活动表、存档表合并分区以及存档表的新分区的边界
    SELECT @MergeRange=CONVERT(SMALLDATETIME,value) FROM sys.partition_range_values, sys.partition_functions WHERE sys.partition_functions.function_id = sys.partition_range_values.function_id AND sys.partition_functions.name = 'E_Alive_Partition_Func' AND boundary_id = 1
    SELECT @SwitchRange=CONVERT(SMALLDATETIME,value) FROM sys.partition_range_values, sys.partition_functions WHERE sys.partition_functions.function_id = sys.partition_range_values.function_id AND sys.partition_functions.name = 'E_Alive_Partition_Func' AND boundary_id = 2

    BEGIN TRANSACTION
    ALTER PARTITION SCHEME [E_Alive_Partition_Schema] NEXT USED [PRIMARY]
    ALTER PARTITION SCHEME [E_Staging_Partition_Schema] NEXT USED [PRIMARY]
    
    --在活动表中新增分区
    ALTER PARTITION FUNCTION [E_Alive_Partition_Func]()SPLIT RANGE(CONVERT(NVARCHAR,@SplitRange,120))
    --在存档表中新增分区           
    ALTER PARTITION FUNCTION [E_Staging_Partition_Func]()SPLIT RANGE(CONVERT(NVARCHAR,@SwitchRange ,120))
    --切换分区    
    ALTER TABLE [Alive_Table] SWITCH PARTITION 2 TO [Staging_Table] PARTITION 2
    
    --合并活动表分区与存档表分区
    ALTER PARTITION FUNCTION [E_Alive_Partition_Func]() MERGE RANGE(CONVERT(NVARCHAR,@MergeRange,120))
    ALTER PARTITION FUNCTION [E_Staging_Partition_Func]() MERGE RANGE(CONVERT(NVARCHAR,@MergeRange,120))

    COMMIT TRANSACTION
END

在整个滑动窗口的操作过程中,活动表和存档表分别合并和拆分了两次,有四个相关边界值。而由于活动表的合并边界值和存档表的合并边界值是一样的,所 以实际有三个边界值。其中合并边界就是第一个分区和第二个分区的边界,而存档表的拆分边界就是活动表的第二个分区和第三个分区的边界,这些都可以通过 sys.partition_range_values, sys.partition_functions表获得。所以这个存储过程只 需要输入一个变量,即活动表新拆分出的分区的边界

注意

  1. 由于新拆分的分区中非聚集索引不会应用原来的压缩方式,所以如有需要,应当在存储过程中补充对相应索引做压缩的操作。
  2. 之所以在存储过程中先进行分区的拆分,再进行分区切换,最后进行分区合并,是考虑对空的分区(切换前的存档表的第二分区、切换后的活动表的 一、二分区)进行拆分或者合并效率比较高。
  3. 以上只是Slide Window的一种方式,事实上,如果对历史数据不那么在意,我们依然可以用分区切换的方式,将旧的数据移出然后删除。或者使用多个存档表,每次都将活动 表的最后一个分区移到新的存档表中,这样省去了合并存档表分区的性能消耗,但多个存档表可能在管理上会比较麻烦。

后记:

关于数据库的“压缩”、“分区”、“滑动窗口”,这里就算告一段落了。虽然题目是“SQLServer性能优化”,其实这里提到的仅仅是关 于性能优化比较偏门的一小部分,最常用的类似“索引”、“查询结构”之类的性能优化技巧并没有涉及。

而即使是这一小部分,也是诚惶诚恐。虽然这些技巧都在实际应用中实践过,但真要写出来,却还是有些力不从心,写博的过程基本就是重新学习的 过程,其间翻阅了很多资料,不求有功,但求无过,不至于误人子弟。但毕竟百密一疏,而且即使看的资料,也不敢保证来源真确。所以来往过客,如有个中高手, 能指点出文中瑕疵疏漏,不至于谬误流传,小弟不胜感激。

[转载]批量发布Flash文件

mikel阅读(1116)

[转载]批量发布Flash文件 – 啊…… – 博客园.

我现在主要的工作是负责做多媒体动画了,我不会绘画,也不懂设计,不过我会写程序。好呆也是做过.net编程的。

大家Flash动画做了上千个,要发布产品了,于是研发主管招唤大家一起发布,可我是个懒人,首先就想,有没有批量发布的程序。

网上搜了一下,还真有。是用jsfl写的。

代码看懂了,又找了些jsfl的教程看了看,于是决定扩展一下功能,写个flash插件出来,至少带个操作界面,用时方便,毕竟这个东东不只是我 用。

这个flash插件功能很简单,能够批量发布一个或多个文件夹下的fla文件,包括其子目录下的;设定好,让它慢慢发布就行了,还算实用,至少能满 足我现在的工作。

首先是一个UI。

PublishBatUI.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<dialog buttons=”accept, cancel”  title=”批量编译Flash文档” >
<vbox>
<checkbox id=”cbSubDir” label=”是否包括子文件夹” checked=”true” accesskey=”s” />
<!–<checkbox id=”cbOnlyUnpublished” label=”是否只发布更新过的Flash” checked=”true” accesskey=”u” />–>
<label value=”Flash文档所在路径: (多个路径请换行)” />
<!–<button target=”mm” id=”btnSelPath” label=”选择文件夹”/>–>
<textbox id = “tbPaths” size=”100″ height=”300″ multiline=”true”/>
<!– <label value=”发布后的路径:(默认为.fla文件的当前路径)” />
<textbox id = “pubpaths” size=”100″ multiline=”false”/>
<checkbox id=”cbIsSaveFlaPath” label=”是否按.fla文件存放路径,保存发布后的.swf文件” checked=”true” accesskey=”p” />–>
<vbox>
</dialog>

文件名,就是PublishBatUI.xml。

然后就是Jsfl代码了。

批量发布Fla.jsfl

//批量发布Flash文件。
var tempDoc=undefined;
if(fl.documents.length==0){
//xmlPanel need a document, if there is none, create a temp document
tempDoc=fl.createDocument();
}
// 创建操作界面
useUI = fl.getDocumentDOM().xmlPanel(fl.configURI + “Commands/PublishBatUI.xml”);
//计数
var pubNum=0;
if(tempDoc){
//close temp document
fl.closeDocument(tempDoc);
}
if(useUI.dismiss==”accept”){
// 是否包括子目录
var isSubDir=useUI.cbSubDir;
//fl.trace(isSubDir);
// 是否只发布更新后的
//var isOnlished=useUI.cbOnlyUnpublished;
//源文件路径
var txtPaths=useUI.tbPaths.split(“\r\n”);
//打开选择窗
//var folderURI = fl.browseForFolderURL(“请选择要编译的文件夹:”);
//fl.trace(folderURI)
for(var i=0; i<txtPaths.length; i++)
{
var path=txtPaths[i]=”file:///”+txtPaths[i].split(“:”).join(“|”).split(“\\”).join(“/”);
pubBatFla(path,isSubDir);
}
fl.trace(” 操作完成,累计生成”+pubNum+”个。”);
}
//
//批量发布Fla文件
//flaDir:fla所在的文件 夹;
//isSubDir:是否编译子文件夹下的fla,true为编译为子文件夹;
function pubBatFla(flaDir,isSubDir)
{
//当前目录下的文件
var files= FLfile.listFolder(flaDir,”files”);
for (var i=0; i<files.length; i++) {
pubFla(flaDir+”/”+files[i]);
}
//不再编译子文件夹
if(!isSubDir)return;
// 当前目录下的子目录
var subDir= FLfile.listFolder(flaDir,”directories”);
for (var j=0; j<subDir.length; j++) {
pubBatFla(flaDir+”/”+subDir[j],isSubDir);
}
}
//发布fla文件
//fileURL:完整的Fla文件路径
function pubFla(fileURL)
{
if(fileURL.indexOf(“.”)>-1)
{
//当前文件后缀名
var flExt= fileURL.substr(fileURL.lastIndexOf(“.”));
// 如果是fla文件,则执行发布
if(flExt.toLowerCase() == “.fla”){
var doc=fl.openDocument(fileURL);
doc.publish();
doc.close();
pubNum++;
}
}
}

文件名保存为“批量发布Fla.jsfl”

将两个文件放置到如下目录下:

如果是Flash8,放到C:\Documents and Settings\Administrator\Local Settings\Application Data\Macromedia\Flash 8\zh_cn\Configuration\Commands

如果是Flash CS3,放到C:\Documents and Settings\Administrator\Local Settings\Application Data\Adobe\Flash CS3\zh_cn\Configuration\Commands

重新打开Flash,不管是flash8还是flash cs3,在其主菜单“命令”中,都会看到“批量发布fla”的命令。

下载:批量发布flash.rar

[转载]游标与事物与错误消息机制

mikel阅读(1085)

[转载]游标与事物与错误消息机制 – 交流空间 – 博客园.

一、游标概念: 将某一结果集作为一个集合处理,且每次处理数据集的一行或一行的某些字段。

建立游标结构如下:

1. 定义游标,将游标与Transact-SQL语句的结果集相关联。

Declare @bookid int, @bname varchar(50),@bindex int

Declare book_cursor  cursor for

Select bookid,bookname,bookIndex from Bas_bookList

2.  执行Transact-SQL语句数据集填充游标即打开游标

Open book_cursor

3.  从游标中检索到第一行,并提取第一行或第一行的某些字段。

Fetch  next  from book_cursor  into @bookid,@bname,@bindex

4.  根据需要对当前行进行操作

@@Fetch_status包括三种状态 0,-1,-2。以此来判断游标执行是否正确。

0则游标执行正确,-1 游标中出现错误,-2 找到空行

While @@fetch_status=0

Begin

Delete update insert 等等

Fetch next  from book_cursor  into @bookid,@bname,@bindex  选取下一行数据

End

4.  关闭游标

Close book_cursor

Deallocate book_cursor

说明: 客户端游标,被odbc所支持,在使用时会有一些限制,只能使用只进和静态游标,它是把结果缓存到客户端,所有游标的操作都由客户端高速缓存下来。并不在 服务器端执行,一般情况下都不这样使用, 只是对一些服务端不支持的Transact-sql和批处理才使用。

这小段只是我对客户端游标的理解,仅作参考。

二、事物,用起来很简单这里就不在详细介绍了。

1. 在存储过程中使用事物

语句结构:

事务起始点: Begin transaction

提交事物,完成自事物起始点开始的数据操作变化,释放事务所占用的资源:Commit TranSaction

如果事务出现错误,回滚:Rollback

在事务起始点,begin transaction  tran1 使@@TRANCOUNT 按 1 递增

执行事务,commit ttansaction tran1    使@@TRANCOUNT 按1 递减,直到减少到0

回滚是到事务的起点或事务的某个保存点也就是定义点。

2. 在C#程序中也可以使用事物

Using(System.Data.SqlClient.SqlConnection conn=new System.Data.SqlClient.SqlConnection(“数据库连接字符串”))

{

conn.open();

using (System.Data.SqlClient.SqlTransaction trans=conn.BeginTransaction())

{

Try

{

sql语句 ;

Trans.Commit();

}

Catch

{

Trans.Rollback();

}

}

}

三、Transact-SQL实现类似于C#语言中的异常处理。Transact-SQL语句组可以包含在TRY块中,如果TRY块内部发生错误, 则会将事件处理转到Catch块中。

语句结构

BEGIN TRY

Transact-SQL语句

END TRY

BEGIN CATCH

错误处理机制

END CATCH

其实以上讲述的基础知识。刚开始从事开发工作就知道明白,会用了。

此文只是系统地总结一下。供大家参考。算不上精辟。

我在实际的应用中发现一个问题,对于一个复杂的存储过程,把上面三种用法综合到一起,会提高不少的执行效率。一是为了找到错误点,回滚事物,把 try和 transaction组合到一起,如果大量数据要处理,可能会用到游标,有时候在想,事物当执行commit的时候才会永久地处理数据,是不是在用游标 的时候也这样,把游标写到事物里,把所有的游标都执行完毕,再进行事物处理,如果异常则回滚。试了一下,果然快很多。而且在Transact-Sql里同 一存储过程定义的变量,在整个运行周期都是有效的,这就很好将整个构想实现了。例如:

SET NOCOUNT ON;

BEGIN TRY

BEGIN TRANSACTION    tran1

DECLARE @proarageid BIGINT,@procomid BIGINT,@proagentid BIGINT,@progropid BIGINT

—语句

DECLARE acursor CURSOR

FOR SELECT id,provicename,cityname FROM Ass_ArrearageTemporary

OPEN acursor

FETCH NEXT FROM acursor INTO @proarageid,@procomid,@proagentid                 WHILE @@FETCH_STATUS = 0

BEGIN

—语句

FETCH NEXT FROM acursor INTO @proarageid,@procomid,@proagentid

END

COMMIT TRANSACTION tran1

CLOSE acursor

DEALLOCATE acursor

END TRY

begin CATCH

IF @@TRANCOUNT > 0

BEGIN

CLOSE acursor

DEALLOCATE acursor

ROLLBACK  TRANSACTION tran1

return

END

END CATCH

虽不是含量很高,但也是笔者的心血。

[转载]ASP.NET MVC 环境配置,从1.0到2.0的转换和学习资源等

mikel阅读(825)

[转载]ASP.NET MVC 环境配置,从1.0到2.0的转换和学习资源等 – 凭海观澜 – 博客园.

一、下载地址:

下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyID=c9ba1fe1-3ba8-439a-9e21-def90a8615a9&displaylang=en

在4.12号发布的vs 2010正式版,Visual Web Developer 2010正式版中将会置对ASP.NET mvc2的支持.

在页面底部有三个文件下载ASP.NET-MVC-2-RTM-Release-Notes.doc、AspNetMVC2_VS2008.exe 和mvc2-ms-pl.zip。下载完后安装AspNetMVC2_VS2008.exe即可,

注意:前提是你必须安装了vs2008sp1:

下载地址: http://www.microsoft.com/downloads/details.aspx?familyid=27673C47-B3B5-4C67-BD99-84E525B5CE61&displaylang=zh-cn

二、从1.0到2.0的转换

http://weblogs.asp.net/leftslipper/archive/2009/10/19/migrating-asp-net-mvc-1-0-applications-to-asp-net-mvc-2.aspx

在Download下面点链接下载

The app is a single executable: Download MvcAppConverter.zip (220 KB).

解压缩后选择对应的MVC1.0的solution进行转换即可

三、已安装vs2010beta时的解决办法:

在ASP.NET-MVC-2-RTM-Release-Notes.doc中有这样的说明:

Note

Because Visual Studio 2008 and Visual Studio 2010 RC share a component of ASP.NET MVC 2, installing the ASP.NET MVC 2 RTM release on a computer where Visual Studio 2010 RC is also installed is not supported.

也就是说在安装完vs2010beta后,再安装AspNetMVC2_VS2008.exe会提示已经安装完成,但是vs2008缺没有对应的 MVC2,如果打开包含MVC2的Project,会报如下的错误:

The project type is not support by this installation.

我的解决方法是:

在不卸载2010的情况只需要从添加、删除程序里面把
Microsoft ASP.NET MVC2和Microsoft ASP.NET MVC2-visual studio 2010 tools卸载,然后再装AspNetMVC2_VS2008.exe即可。

四、学习资源:

http://www.asp.net/mvc/

[转载]淘宝API开发系列--商家的绑定

mikel阅读(1403)

[转载]淘宝API开发系列–商家的绑定 – wuhuacong(伍华聪)的专栏 – 博客园.

在上篇《淘宝API开发系列 –开篇概述》介绍了下淘宝API平台的一些基本知识,由于一直有事情忙,就没有及时跟进随笔的更新,本篇继续讨论淘宝API的开 发知识,主要介绍商家的绑定操作。上篇我们说过,淘宝就是基于应用程序键来控制用户的访问频率和流量的,另外可 以通过应用程序键,让使用者登陆确认,获取到相关的授权码,然后获取SessionKey,作为访问使用者淘宝资源(如买入卖出等私人记录的信息)

我们再看看 SessionKey是如何获取的(下面是淘宝关于正式环境下SessionKey的说明):

正式环境下获取SessionKey

注意:web插件平台应用和web其它应用在正式环境下是同样的获取 方法

1、WEB应用

例如回调URL 为:http://localhost

访问 http://container.open.taobao.com/container?appkey={appkey},页面会跳转到回调URL,地 址类似如下:

http://localhost/?top_appkey={appkey} &top_parameters=xxx&top_session=xxx&top_sign=xxx

回 调url上的top_session参数即为SessionKey
2、客户端应用

访 问 http://auth.open.taobao.com/?appkey={appkey},即可获得授权码

通 过http方式访问 http://container.open.taobao.com/container?authcode={授权码},会得到类似如下的字符串

top_appkey=1142&top_parameters=xxx&top_session=xxx&top_sign=xxx

字符串里面的top_session值即为SessionKey。

由 于本篇文章主要是介绍C/S客户的应用,因此客户端的应用就不能通过回调Url方式获得用户的验证,我们可以通过在Winform中的 WebBrowser控件,显示一个登陆验证及访问确认的操作界面给客户,当客户确认的时候并返回Session Key的内容界面的时候,我们取出Session Key保存并关闭浏览器窗口即可,今后把该SessionKey作为参数来访问相关需要Session Key的API即可。

另外,由于SessionKey的间隔时间比较短,如果API调用间隔时间比较长,那么SessionKey有可能 失效的,但是我们注意到,如果API调用的时候,SesionKey过期 那么会抛出TopException(其中ErrorCode为26或者27是SessionKey过期),里面有关于与TopException的部分 说明如下:

26 Missing Session 缺少 SessionKey参数
27 Invalid Session 无效的SessionKey参数

我 们先看看具体实现的界面,然后分析其中的实现逻辑吧。

1、首次需要登录的时候,使用一个Winform嵌套一个WebBrowser控件, 实现网页登录。

2、商家用户输入账号密码后,确认是否授权程序访问相关资源。

3、确认后生成SessionKey,这个Key正是我们的程序需要的关键内容,因此需要自动获取出来。

4、程序拿到该Session Key后,把它作为参数来访问淘宝API获取相关的信息,这里获取交易API的购买信息,需要SessionKey的。

以上就是使用SessionKey的API工作流程界面,我们下面介绍一下相关的实现代码。

1) 主窗体主要的操作代码:

代码

public partial class Form1 : Form
{
private TopJsonRestClient jsonClient;
private TopContext context;

private void Form1_Load(object sender, EventArgs e)
{
this.winGridView1.ProgressBar = this.toolStripProgressBar1.ProgressBar;
this.winGridView1.AppendedMenu = this.contextMenuStrip1;

jsonClient = new TopJsonRestClient(http://gw.api.taobao.com/router/rest, 12033411, 你的密钥);

client = GetProductTopClient(json);
xmlClient
= new TopXmlRestClient(http://gw.api.taobao.com/router/rest, 12033411, 你的密钥“”);
}

/// <summary>
/// 判断是 否顺利获取SessionKey
/// </summary>
/// <returns></returns>
private bool GetAuthorizeCode()
{
string authorizeCode = “”;
FrmAuthorized dlg
= new FrmAuthorized();
if (dlg.ShowDialog() == DialogResult.OK)
{
authorizeCode
= dlg.AuthrizeCode;
}
if (string.IsNullOrEmpty(authorizeCode)) return false;

context = SysUtils.GetTopContext(authorizeCode);
if (context == null) return false;

return true;
}

private void BindData()
{
if (context == null)
{
bool flag = GetAuthorizeCode();
if (!flag) return;
}

string sessionKey = context.SessionKey;

////获取用户信息
//UserGetRequest request = new UserGetRequest();
//request.Fields = “user_id,nick,sex,created,location,alipay_account,birthday”;
//request.Nick = “wuhuacong”;
//User user = client.Execute(request, new UserJsonParser());
//MessageBox.Show(ReflectionUtil.GetProperties(user));

try
{
//买入交易
TradesBoughtGetRequest req = new TradesBoughtGetRequest();
req.Fields
= tid,title,price,type,iid,seller_nick,buyer_nick,status,orders;
req.PageNo
= 1;
req.PageSize
= 10;
ResponseList
<Trade> rsp = jsonClient.GetBoughtTrades(req, sessionKey);
this.winGridView1.DataSource = rsp.Content;
MessageBox.Show(rsp.Content.Count.ToString());

//卖出交易
TradesSoldGetRequest soldReq = new TradesSoldGetRequest();
soldReq.Fields
= tid,title,price,type,iid,seller_nick,buyer_nick,status,orders;
soldReq.PageNo
= 1;
soldReq.PageSize
= 10;
ResponseList
<Trade> soldRsp = jsonClient.GetSoldTrades(soldReq, sessionKey);
this.winGridView1.DataSource = soldRsp.Content;
MessageBox.Show(soldRsp.Content.Count.ToString());
}
catch (TopException ex)
{
if (ex.ErrorCode == 26 || ex.ErrorCode == 27)
{
if (MessageUtil.ShowYesNoAndError(SessionKey过期,您是否需要 重新认证) == DialogResult.Yes)
{
bool flag = GetAuthorizeCode();
if (!flag) return;

BindData();//重新刷新
}
else
{
return;
}
}
}
}

private void btnTest_Click(object sender, EventArgs e)
{
BindData();
}

2、 用户登陆的窗体,就是一个form窗体加上一个WebBrowser控件,窗体代码如下:

代码

public partial class FrmAuthorized : Form
{
/// <summary>
/// 授权码
/// </summary>
public string AuthrizeCode = “”;
private string url = http://open.taobao.com/authorize/?appkey=12033411;

public FrmAuthorized()
{
InitializeComponent();
}

/// <summary>
/// 获取 HTML页面内制定Key的Value内容
/// </summary>
/// <param name=”html”></param>
/// <param name=”key”></param>
/// <returns></returns>
public string GetHiddenKeyValue(string html, string key)
{
string str = html.Substring(html.IndexOf(key));
str
= str.Substring(str.IndexOf(value) + 7);
int eindex1 = str.IndexOf();
int eindex2 = str.IndexOf(\“”);
int eindex = eindex2;
if (eindex1 >= 0 && eindex1 < eindex2)
{
eindex
= eindex1;
}
return str.Substring(0, eindex);
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.AbsoluteUri == url)
{
AuthrizeCode
= GetHiddenKeyValue(this.webBrowser1.DocumentText, autoInput);
if (!string.IsNullOrEmpty(AuthrizeCode) && AuthrizeCode.IndexOf(TOP-) >= 0)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}

private void FrmAuthorized_Load(object sender, EventArgs e)
{
webBrowser1.Navigate(url);
}
}

这 样我们就可以在首次使用API或者SessionKey失效的时候,让商家用户输入账号密码并确认即可,其他使用即可顺利无阻。

是不是有点 意思呢,赶快试试吧,说不定带来一些意想不到的收获及创意哦。

主要研究技术:代码生成工具、Visio二次开发

转载请注明出处:
撰写人:伍华聪  http:
//www.iqidi.com

[转载]网站测试自动化系统—系统应该有的功能 - Killmyday - 博客园

mikel阅读(1166)

[转载]网站测试自动化系统—系统应该有的功能 – Killmyday – 博客园.

在前面几篇文章网站测试自动化系统—基于SeleniumVSTT数据驱动测试在测试代码中硬编码测试数据里,大概介绍了编写测试代码的过程。然而光把代码写完了是不够的,自动化测试不仅仅是将原本手工执 行的测试用例通过编码的方式自动化。一个完整的自动化测试过程应该包括如下几个过程:

1. 在实验室里面自动选择机器来执行测试过程,比如说为了测试一个软件产品,以Office举例。因为微软已经为Windows发布了很多的版本,Windows XP Windows Vista Windows 7等,而每一个版本的Windows还有不同的变种,例如Vista有企业版,旗舰版,专业版等等,每个变种提供的功能有一点的差别。另外,还要考虑在64位和32位操作系 统上安装,还有国际化测试等等。这样一来,为了完全测试Office,测 试矩阵肯定非常大,也许需要测试几百个平台,即使以每个平台需要一台测试机估计的话,也需要几百台机器。如果是纯粹人工来管理这些机器的话,不仅费时费 力,而且出错的几率会很大比如说你不能找一台32位处理器的机器安装64位的操作系统。因此,一般来说,一个大的软件产品团队都会使用或者自己编写工具来管理测试机。

测试网站 也是一样的,需要考虑到浏览器之间的兼容性,不同测试类型需要不同的测试机器,以及国际化等方面的因素,同样会要求不少的机器执行测试。因为这个软件的制 作涉及到分布式开发的一些理念,所以我不会在这系列的文章里讲解如何实现这种系统。

2. 自动准备测试环境,既然机器已经从测试机集群中挑选出来了,下一步就是准备测试环境,例如重装系统 (当然啦,Ghost还原也行),安装产品所依赖的软件,以及安装最新版 本的产品(每日编译完成以后生成的新版本),将自动化测试用例程序拷贝到测试机,准备测试数据等等。

3. 执行自动化测试用例。这一过程,包括我们通常理解的将需要手工执行的测试用例使用编码的方式使之自动 运行。另外,这一过程还包括一些可选的子过程:

a) 自动生成测试用例所需要的测试数据,生成随机的合法的测试数据不是一件容易的工作。虽然你可以random()之类的函数生成随机数据,但是采用这种简单的方法很难生成合法的数据。比如说,为了测试网站的用户 登录系统,大部分网站都是要求用户名不能包括特殊字符,这样你就需要在随机生成数据的过程中添加一些限制条件。

一般来 说,软件产品在接受用户输入的时候,都会有一些不同的限制条件;因此提供一个生成随机但又合法的测试数据的通用代码库不是一件容易的事情。这也是为什么, 我在这系列文章里面,介绍数据驱动测试的原因。

b) 自动生成自动化测试用例。这一步骤并不是说录制测试步骤,根据测试步骤生成C#或者其他语言的代码。这里说的是,软件自动生成测试用例,并生成对应的自动化测试代码。比如说,单 元测试一般就是根据函数的参数,设计对应的测试用例;在程序中,参数类型一般来说都是有限的,要么就是编程语言自带的固定类型,要么就是程序员自定义的类 型。这样我们是有机会根据参数类型,自动生成测试用例的,微软的Pex就是一个这个领域很好的例子。

又比如, 测试人员可以设计产品的模型,即描述产品应该实现的功能,然后通过特定的软件分析这个模型生成测试用例,微软的Spec Explorer就是这方面的例 子。

再比如, 如果你是在测试一个函数库,例如.NET Framework。一般来 说,用户(程序员)使用函数库的时候无非就是一些API的排列组合。我们 可以先针对每个公开的API设计单元测试代码,然后编写一个程序将这些单 元测试用例随机组合,生成新的测试用例。举个例子,假设要测试数据库连接方面的API,先单独根据Open, ReadData, Close等 函数编写好单元测试用例,然后由程序将这些用例随机排列成一些新的用例。当然,随机排列的问题就是会生成非法的调用序列,比如Close, ReadData, Open这个序列的就是非法的。因此测试用例随机产生程序的一个 很重要的工作就是在测试工程师的配合下,移除掉这些非法的序列。

4. 测试结果收集自动化,因为是同时在多台机器上执行测试用例,要求测试人员手工收集测试结果是一个很麻 烦的过程;所以这一部分由程序自动完成是非常必要的, 一般来说,测试用 例执行完毕以后,自动化测试脚本会将测试结果自动发布到一个中心数据库上。项目管理团队会通过一些报表服务例如SQL Server Reporting Services等系统来评估以下几个内容:

a) 产品哪些组件的风险比较高,即容易出错或者没有完整地测试过。

b) 产品的健壮程度。

c) 是否可以发布产品,或者延期发布?

这篇文章大致总结 了自动化测试系统应该完成的任务,本来应该当作绪论写的。不过我觉得可能很多人对纯理论的东西不感兴趣,因此将一些实现细节放在前面先写了。

未完待续……