[转载]ASP.NET MVC3 Service Location

mikel阅读(1027)

[转载]ASP.NET MVC3 Service Location – haogj – 博客园.

介绍

ASP.NET MVC3 的一个重要的新特性就是允许注册一个服务点 Service Location,然后在框架中使用的能力。以前版本的 MVC 已经提供了 Service Location 和依赖注入的机会,在 MVC3 中,我们正式提供了这种能力,并且为开发者开放了多种使用的机会。

总体策略

关于 Service Location 的最重要的部分就是它是可选的,这意味着如果你对 Service Location 不感兴趣,那么,你不需要被强制使用,你总是可以在不使用 Service Location 的情况下,调用自定义的函数。在以后加入新的 Service Location 的时候,也会保持向后的兼容性。

当使用注册的 Service Location 的时候,依赖于具体的使用,MVC 一般将会使用下面三种策略之一:

1. 定位一个唯一的注册服务

现在的 MVC 中使用的许多服务都注册一个实例来提供服务,例如,控制器工厂 Controller Factory,它实现了接口 IControllerFactory。对于整个应用来说,只有一个控制器工厂实例。

当 MVC 试图使用单个的注册服务的时候,它将会首先通过 Service Locator 寻找时候存在一个注册的服务实例,如果有,将使用这个服务实例,如果没有,那么将会回退到没有使用服务定位器时候注册的单个实例。

上面的处理顺序意味着使用服务定位器的用户不必担心现存项目中 MVC 的默认服务。因为当服务提供器不存在的时候,将会自动使用原来注册的服务,这种潜力也意味着可以在两个地方注册自定义的服务,但是只有通过服务器注册的服务被使用。

2. 定位多个注册的服务

在 MVC 中也有为一个服务注册多个服务实例的地方,比如说,视图引擎,视图引擎实现了接口 IViewEngine,典型情况下,MVC 提供了注册多个服务的注册点,也提供了 ViewEngines.Engines 来找到每一个视图引擎,并确定其中之一可以提供服务。还有其他的类似的场合,比如, ModelValidatorProviders.Providers 。

当 MVC 试图使用这种具有多个服务实例的服务的时候,MVC 将会通过管理多个服务实现的 Facade 来完成,Facade 将会把通过静态注册的服务实例和通过 Service Location 注册的服务实例结合在一起来选择合适的实现。在这里,服务的顺序是很重要的,通常意味着通过 Service Location 注册的服务实例要优先静态注册的实例。

类似于单实例服务注册,这意味着对于存在默认服务提供器的时候,不需要再通过 Service Location 来注册服务,这也意味着对于注册的多个服务来说,多数的容器也不必提供一个本地的排序函数,因为如果顺序是重要的,就可能需要非 Service Location 的 API。

3. 创建对象

MVC 使用服务定位器最后的策略就是直接创建对象,这最好通过依赖注入的服务来实现,我们将试图通过 Service Location 来创建对象,一个典型的例子就是控制器对象 Controller。

当 MVC 试图创建新的对象的时候,它将会请求服务定位器来创建这个对象,如果服务定位器不能完成这个任务,那么,将会回退到 MVC2 的行为,通常意味着使用 Activator.CreateInstance 来创建。

IDependencyResolver

为了在 MVC3 中使用服务定位,在 MVC3 中提供了一个接口 IDependencyResolver 和一个新的类 DependencyResolver,

1 public interfac IDependencyResolver
2 {
3 object GetService( Type serviceType );
4 IEnumerable<object> GetServices( Type serviceType );
5 }

DependencyResolver 的定义如下:

public class DependencyResolver
{
public static IDependencyResolver Current { get; }
public static void SetResolver( Object commonServiceLocator );
public static void SetResolver( IDependencyResolver resolver );
public static void SetResolver( Func<Type, Object> getService, Func<Type,  Enumerable<Object>> getServices );
}

三个静态方法提供了注册服务定位器的机制,静态属性 Current 用来获取注册的服务点。

Common Service Locator 提供了一个可以在应用程序或者框架中使用的共享的服务点,同时,项目中也提供了对于常见 IoC 的包装。

Service locator adapter implementations

Implementation
Castle Windsor Adapter
Spring .NET Adapter
Unity Adapter
StructureMap Adapter
Autofac Adapter
MEF Adapter now on .NET Framework 4.0
LinFu Adapter
Multi-target CSL binaries

示例

例如,在程序中我们定义了如下的接口用于获取信息。并提供了两种实现方式:Hello 和 Hi。

namespace mvc_1.study
{
public interface IHello
{
string Message { get; }
}

public class Hello : IHello
{
public string Message
{
get { return Hello, world.; }
}
}

public class Hi : IHello
{
public string Message
{
get { return 世界,你好!; }
}
}
}

项目中使用 Unity 来作为实际的 IoC 容器。类型注册通过配置文件完成。

<configuration>
<configSections>
<section
name
=unity
type
=Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration/>
</configSections>
<unity>
<typeAliases>
<typeAlias alias=singleton type=Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity />
<typeAlias alias=external type=Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity />
<typeAlias alias=perThread type=Microsoft.Practices.Unity.PerThreadLifetimeManager, Microsoft.Practices.Unity />
</typeAliases>
<containers>
<container>
<types>
<type type=mvc_1.study.IHello,StudyModel
mapTo
=mvc_1.study.Hi,StudyModel >
<lifetime type=singleton />
</type>
</types>
</container>
</containers>
</unity>
<configuration>

在程序中,我们可以使用类似于下面的代码来注册服务点。

// 创建 Unity 容器
IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();

// 读取配置文件
Microsoft.Practices.Unity.Configuration.UnityConfigurationSection
config
= System.Configuration.ConfigurationManager
.GetSection(
unity)
as UnityConfigurationSection;

// 通过配置文件设置容器
config.Configure(container);

// 在代码中直接注册,一般不用
// container.RegisterType<mvc_1.study.IHello, mvc_1.study.Hello>();

// 包装为 ServiceLocator
Microsoft.Practices.Unity.ServiceLocatorAdapter.UnityServiceLocator locator
= new Microsoft.Practices.Unity.ServiceLocatorAdapter.UnityServiceLocator(container);

// 注册
DependencyResolver.SetResolver(locator);

在代码中,可以直接通过服务点来获取注册的对象实例。

mvc_1.study.IHello hello
= DependencyResolver.Current.GetService<mvc_1.study.IHello>();
return hello.Message;

关于 unity 容器,可以参考

Enterprise Library – Unity Application Block 学习手册(最新版) Part 1

的 你知道Unity IoC Container是如何创建对象的吗?

注:本文内容主要参考 Brad Wilson 的  blog posts on Service Location

不知什么原因,我的电脑不能访问 Brad Wilson 的博客,手机却可以。手机看起博客来不太方便,错漏之处还请指出

[转载]Android 手机十大必备软件

mikel阅读(1017)

[转载]Android 手机十大必备软件_IT新闻_博客园.

Android是 Google 推出的目前国际流行的新锐智能手机平台,正在吸引越来越多的用户和开发者加入其阵营。本文精选了国内 Android 用户装机必备的十大应用(自然是以具备在线云同步功能的为主),希望为各位安卓的新玩家提供实用参考。

1、聊天必备——QQ

手机 QQ Android 版是腾讯公司专为 Android 平台用户打造的一款随时随地聊 QQ 的手机即时通讯软件,漂亮的主题皮肤设置,触屏手机专业的触屏交互体验,让您和好友得沟通仅在一指之间,处处透出您的生活精彩。

手机下载地址:3g.qq.com

2、学习必备——云词(电子词典)

人们在学习中的遗忘是有规律的,遗忘的进程很快,并且先快后慢。云词正是采用了遗忘曲线算法,会在最佳的复习时刻自动提醒用户进行单词复习,让用户在英语学习上取得事半功倍的效果。

手机下载地址:wap.waptw.com(搜云词即可)

3、上网必备——UCweb

选择 Android 系统手机的朋友很多都是出于网络来考虑的,推荐一款 Android 手机通用手机浏览器——UC浏览器,这就是国内非常出名的UC浏览器的 Android 版本,其功能设置众多且符合国人习惯,支持手机式网页显示,节省流量等。

手机下载地址:wap.ucweb.com

4、阅读必备——iReader阅读器

用过很多的手机阅读类软件,而今天为大家推荐的则是 iReader 阅读器,一款能够阅多数电子书格式,同时又支持自定义文本编码(转换乱码的最佳工具),同时启动速度和预览速度都非常快的软件。

手机下载地址:wap.waptw.com(搜 iReader 阅读软件)

5、输入必备–搜狗手机输入法

搜狗手机输入法在 Android 平台的炫彩皮肤,手势输入,强大的通讯录联想功能很受广大用户的喜爱!

手机下载地址:wap.sohu.com/pinyin

6、任务管理必备——ProcessManager

目前使用过的所有免费版 Android 任务管理器中最好用、最实用同时也是最简单的应用的任务管理器,它的名字就是——Process Manager。还支持卸载软件的功能,就是最后一个选项卡,非常方便,只要点击所选择软件即可完全删除,在也不用安装相关卸载软件或者是进入程序管理界 面了。

手机下载地址:wap.waptw.com(搜 ProcessManager)

7、通讯必备–火种通讯录

Android 平台下一款好用的通讯录软件,拥有华丽的操作界面,弥补了 Android 系统原电话本对汉字的归类和查询界面不友好的遗憾,并提供多方位智能查找功能,字母导航,区域搜索等,提供智能IP设置,通讯录备份,短信信息备份,手机 软件备份,以及提供新浪微博接口(可直接调用摄像头,方便随时随地记录心情)。

手机下载地址:m.hozom.com

8、安全必备—-360安全卫士

一款完全免费的手机安全软件,集防垃圾短信,防骚扰电话,防隐私泄漏,对手机进行安全扫描,联网云查杀恶意软件等,360手机卫士便捷实用的功能,全方位为手机安全及隐私保护。

手机下载地址:m.360.cn

9、播放必备——天天动听

是一款功能强大、完全免费的手机音乐播放软件,支持歌词和歌曲图片下载,皮肤随心更换,更有炫丽震撼的可视化效果,同时预置丰富的均衡器效果,支持音效增强,简洁人性化的操作,带来手机听歌的全新体验,是拇指一族必备的音乐播放工具。

手机下载地址:bbs.ttpod.com/wap

10、启动必备— Autostarts 开机自启动项管理

随着安装的软件越来越多,机器本身的开机速度也越来越慢,开机需要加载的项目严重拖慢了每次开机的时间,这个时候,我们就需要这款软件,极大的缩短了开机时间。

手机下载地址:wap.waptw.com(搜Autostarts)

[转载]Visual Studio 2008单元测试(1)_开篇

mikel阅读(1101)

[转载]Visual Studio 2008单元测试(1)_开篇 – MyNet – 博客园.

说到单元测试,引用《单元测试之道C#版》里面的一段话:
单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。例如,你可能把一个很大的值放入一个有序list  中去,然后确认该值出现在list  的尾部。或者,你可能会从字符串中删除匹配某种模式的字符,然后确认字符串确实不再包含这些字符了。
执行单元测试,是为了证明某段代码的行为确实和开发者所期望的一致。
其实进行单元测试很简单,下面本人介绍Visual Studio 2008自带的单元测试功能:
第一步:首先建立一个C#类库项目,其中增加一个Contract类,此类有一个GetContractNameByGUID方法,具体代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Business
{
public class Contract
{
private string _ContractName;
public string ContractName
{
get
{
return _ContractName;
}
set
{
_ContractName = value;
}
}
public Contract()
{
}
public Contract(string contractName)
{
this._ContractName = contractName;
}
//通过合同GUID获取合同名称
public string GetContractNameByGUID (string strContractGUID)
{
if (strContractGUID.Length > 10)
{
return “10”;
}
else
{
return “8”;
}
}
}
}
第二步:创建单元测试代码
在Visual 2008里面创建单元测试代码其实很简单,在类名单击鼠标右键,点击“创建单元测试”菜单即可,如下图所示:
然后弹出“创建单元测试”的对话框,可选择当前程序集中的类的函数创建单元测试项目,默认选择当前类,如下图所示:
点击“确定”,Viual 2008会自动生成ContractTest类,包括GetContractNameByGUIDTest函数供测试GetContractNameByGUID,如下图所示:
其中,strContractGUID为GetContractNameByGUID函数的输入参数,默认值为 string.Empty,expected变更为预计输出值,默认值也为string.Empty,需要我们进行个性化设置。 Assert.AreEqual为验证指定的值是否相等的函数,如果不相等则认为失败,就是通过此方法来测试函数的输入与我们的预计输出是否相 等,Assert.Inconclusive代码为输出结果时显示的内容,我们不需要显示,只需要显示错误信息即可,因此需要删除掉此行代码。我们将自动 生成的代码改造如下:
///

///GetContractNameByGUID 的测试
///
[TestMethod()]
public void GetContractNameByGUIDTest()
{
Contract target = new Contract(); // TODO: 初始化为适当的值
string strContractGUID = string.Empty; // TODO: 初始化为适当的值
string expected = string.Empty; // TODO: 初始化为适当的值
string actual;
actual = target.GetContractNameByGUID(strContractGUID);
Assert.AreEqual(expected, actual);
Assert.Inconclusive(“验证此测试方法的正确性。”);
}
///
///GetContractNameByGUID 的测试
///
[TestMethod()]
public void GetContractNameByGUIDTest()
{
Contract target = new Contract(); // TODO: 初始化为适当的值
string strContractGUID = ”  111111111   “; // TODO: 初始化为适当的值
string expected = “8”; // TODO: 初始化为适当的值
string actual;
actual = target.GetContractNameByGUID(strContractGUID);
Assert.AreEqual(expected, actual);
}
第三步:执行测试代码
在Visual 2008可以很方便执行测试代码,可点击“运行上下文中的测试”按钮进行测试,如下图:
执行完后,可在“测试结果”窗口查看我们的单元测试结果,如下图所示:
从结果可知,测试结果不能过,可通过查看错误信息帮助我们找出错误原因,原来” 111111111  “字符串前后都存在空格,字符串的长度大于10,我们判断长度时应该去除掉前后的空格,将代码改造如下:
//通过合同GUID获取合同名称
public string GetContractNameByGUID (string strContractGUID)
{
if (strContractGUID.Trim().Length > 10)
{
return “10”;
}
else
{
return “8”;
}
}
重新执行测试代码,结果如下:
测试通过,代码没有问题。
本篇简单介绍了Visual2008最简单的单元测试功能,下期将介绍如何利用Visual2008进行Web页面的测试

[转载]分享一个基于jQuery的锁定表格行列的js脚本

mikel阅读(1026)

[转载]分享一个基于jQuery的锁定表格行列的js脚本。 – 金色海洋工作室 – 博客园.

网上也有很多锁定行列的方法,一个是使用css,另一个就是专门的控件附带有锁定的功能。css的大多数锁定行,而不能锁定列。好像看过园子里的司徒正美,写过一个用css锁定行列的,当时css比较烂看不懂,也没有保存那个网址(很后悔),现在想要找却又找不到了。

另一个就是第三方控件,这种控件很强大,锁定行列只是附带的一个小功能。但是有一个比较明显的缺点,必须使用它的控件,我想锁定GridView,那就不行了。除非你能把他的锁定方法给研究出来。

最近我在学JQuery,我觉得找个需求来学习,进步会比较快,于是就选择了锁定行列的这个需求。

目的:

1、针对<table>来锁定,只要是table标签的形式都能锁定。支持GridView等控件。

2、可以锁定行、锁定列、同时锁定行列、锁定多行多列。

3、使用简单,无需修改后台代码(后置代码)。只需要在前台稍微做点调整即可。

4、效率不能太差,最好支持多种浏览器。

目的确定下来,然后就要想办法实现了。其实以前也做过两个版本,因为以前js很烂,也不知道有JQuery这样的东东,于是就想了一个笨法。先 做一个div(divMain),把要锁定的table放进去,再做三个div,然后把要锁定的table拷贝到三个div里面,然后调整div的宽度、 高度和位置,分别放在要锁定的行、列和行列交叉的地方放。然后在写一个滚动事件,在divMain的滚动条滚动的事件里,同时滚动上面的div和左面的 div。这样就形成了一个锁定的效果。

这个方法的缺点很多了,但是水平很烂,也只能这样了。现在想要提高一下js水平,那么就要弄个更好一点的。把整个table都拷贝过去是不是太浪费了?能不能只拷贝要锁定的行、列?

于是呢,就要JQuery动态创建div和需要的table,然后调整他们的宽度、高度和位置,这样在滚动的时候效率就高了很多,不过也有个问 题,那就是精确获取、设置td的高度和宽度,要能够支持被撑高的td。这个问题困扰了我好久,昨天在群里得到了各位高手的帮忙,尤其是“紫風鈴”的指点, 才得以突破。

说了这么多,可能大家都烦了,说一下使用方法。

1、引用jQuery-1.4.2.js

2、引用scroll-1.0.js (下载

3、在要锁定的table外面加上一个div,并且设置id

4、调用js函数,myScroll(‘div_Main’,1,1,’tableID’)

第一个参数:要锁定的table外面的div的ID,

第二个参数:要锁定的行数(从上面数),可以是0,表示不锁定行。

第三个参数:要锁定的列数(从左面数),可以是0,表示不锁定列。

第四个参数:要锁定的table的ID。

好了搞定。有几个注意事项。

1、如果div里只有一个table,没有其他的,那么可以不传递tableID这个参数。

2、table的width不能设置百分比的形式,比如100%,这样很可能造成table被挤在div里面,没有横向的滚动。

对了,还要说一下缺点:

1、代码比较烂。初学jQuery,js的功底也很差,所以现在的1.0版本的代码只是实现了基本的功能,代码的美观、运行效率那就很差了,以后还需要继续前进。

2、td的高度和宽度还是差了一些,不过基本上可以忍受。还需要继续调整。

3、table的行数比较多时(大于100行),初始化时间会很长。初始化就是创建锁定的行、列的部分。

最后是在线演示的地址:http://demo.naturefw.com/Nonline/other/default.aspx

下一步除了修改bug外,还要实现交替色、鼠标跟随、单击、双击、选择变色等功能。

[转载]Android 机顶盒手势、数据分页演示DEMO

mikel阅读(1025)

[转载]Android 机顶盒手势、数据分页演示DEMO – Terry_龙 – 博客园.

上篇讲了一篇机顶盒的一个封装类《GridView》,利用这个封装的GridView 可以实现一些例如移动、位移图标等基础组件“GridView”无法实现的一些功能。本篇将会提出一部分可供运行的代码演示一个分页、手势换屏的DEMO版本,供大家学习。

DEMO 的工程目录如下:

包名解释:

  • com.yaomei.activity.adapter     DEMO使用到的自定义Adapter
  • com.yaomei.activity.info      DEMO入口
  • com.yaomei.dbHelper       数据库帮助类
  • com.yaomei.model        应用程序JAVA BEAN
  • com.yaomei.util          手势换屏需要用到的动画
  • com.yaomei.widget        DEMO 版里面使用到的封装类,包括一个分页控件、一个列表控件GridView 、一个支持动画效果的ViewFlipper

Demo 运行效果如下:

如果你觉得不想用手势,也可以通过点击上面的页码进行定位到哪页,如果你有好几十页的情况效果更好

Tip:本源码为开源DEMO,你可以完全拿去改、或者在此基础上增加功能,请勿作商用。谢谢。运行本源码请使用800*480分辨率的模拟器。

关于GridView 的OnKeyDown  事件,其实应该是放在GridViewExt.java 里面的,下载此源码的朋友可以从Activity 里面将onKeyDown事件的代码放置 在GridView 里面,使其默认支持按键选中功能,然后在Activity里面实现OnkeyDown return Gridview 的OnKeyDown 即可以让其有这个事件。如果你不嫌Activity 里面代码量太多的话,可以不用更改。

源码下载:DEMO

[转载]ASP.NET MVC开源社区项目Orchard基本概念

mikel阅读(1041)

[转载]开源社区项目Orchard基本概念 – 周金根 – 博客园.

前一篇我们看一下基于ASP.NET MVC的开源社区项目Orchard,今天简要介绍一下Orchard的一些基本概念,也算为后期深入学习做些准备。

CMS

CMS是内容管理系统的缩写, ‘C’指的是内容, 内容是网站中的任何信息,例如一篇blog、一个回复,甚至一个导航菜单、公司logo等。如果有权限,我们可以在系统后台进行网站和内容的管理,这就是’M’。而 ‘S’ 是系统,这是个比较模糊的概念。

Content Item

内容项指的是一块单独的内容,通常与一个网站单独的URL关联起来,例如页面、blog等

Content type

内容项是内容类型的实例。

Content Part

在Orchard中内容类型是由一些小的构件块(parts)组成,我们叫做content parts, Content parts 是跨内容类型的可重用的原子内容。

例如一个blog由多部分组成,回复、tags或者打分等content parts,这些part都是可以在其他内容类型中重用的。

Content Field

内容字段是每条信息显示的内容项,它又一个名字和与内容匹配的数据类型。

Module

在Orchard中通过模块来进行功能的扩展,它的文件存在于网站的Modules子目录下。我们可以从Orchard Gallery中安装模块

Feature

一个模块由一个或多个功能组成,我们可以分别允许或禁止单独使用这些小功能。例如定制认证模块能够把OpenID, FaceBook, LiveID, Twitter 或者 Google 认证都分开来,可以单独控制使用哪一个。功能之间是互相依赖的,依赖的功能也可能存在于不同的模块中。

Manifest

清单时一个描述模块或主题的一个文本文件,下面是一个示例:

Theme

当我们设计网站时,能够更改网站外观是很重要的。Orchard区分内容管理和内容展现,通过主题来扩展网站外观。
一个主题就是一个网站外观的包,这个包包括style sheets, images, layouts, templates 和定制代码等。甚至可以继承其他的主题生成一个新的主题,这在进行小改动时很有用。

Layout

布局是主题中定义页面通用布局的一个文件。一个布局通常定义了一套包含内容或者widgets的区域(zone)。

Zone

区域是不居中一个放置widgets的特定part。在一些主题中,区域可以在没有widget时折叠起来

Widget

一个widget是一个小的UI块,它可以添加在网站的所有页面上。例如云标签、查询窗体、地图、或者最近blog列表等

Layer

层是一组通过特定规则激活的widgets。例如当选择首页时激活TheHomePage层,不管什么页面显示时都激活The Default layer

Template

每个content part, 每个 field 和每个widget都需要在前端显示出来,模板把这些不同格式的数据转化成浏览器能够解析的HTML来显示。

Placement

参考:http://orchardproject.net/docs/Basic-Orchard-Concepts.ashx

[转载]一小段jQuery代码的分析与优化

mikel阅读(1006)

[转载]一小段jQuery代码的分析与优化 – Novice Doodle from Gray Zhang – 博客园.

今天刚回家,QQ群里就看到有人求助优化一段JQuery代码,简单看了一下,发现如果对JQuery这东西只停留在用的层面,而不知其具体实现的话,真的很容易用出问题来。这也是为什么近期我一直不怎么推崇用JQuery,这框架的API设定就有误导人们走上歧途之嫌。

需要优化的代码大致是这样的,也不方便直接把人家的代码复制过来,就大概地表达下意思:

$.fn.beautifyTable = function(options) {
    //定义默认配置项,再用options覆盖
    return this.each(function() {
        var table = $(this),
            tbody = table.children('tbody'),
            tr = tbody.children('tr'),
            th = tbody.children('th'),
            td = tbody.children('td');
            
        //单独内容的class
        table.addClass(option.tableClass);
        th.addClass(options.headerClass); //1
        td.addClass(options.cellClass); //2
        //奇偶行的class
        tbody.children('tr:even').addClass(options.evenRowClass); //3
        tbody.children('tr:odd').addClass(options.oddRowClass); //4
        //对齐方式
        tr.children('th,td').css('text-align', options.align); //5
        //添加鼠标悬浮
        tr.bind('mouseover', addActiveClass); //6
        tr.bind('mouseout', removeActiveClass); //7
        //点击变色
        tr.bind('click', toggleClickClass); //8 
    });
};

总的来说,这段代码不错,思路清晰,逻辑明确,想要做什么也通过注释说得很明白了。但是按作者的说法,当表格中有120行时,IE已经反映脚本运行时间过长了。显然从表现来看,这个函数的效率不高,甚至说极其低下。

寻找原因

于是,开始从代码层面进行分析,这是一个标准的jQuery插件式的函数,有个典型的return this.each(function() { ... };);形式的代码,如果作者写下这段代码的时候,不是照本宣科不经思考的话,就应该意识到jQuery的一个函数干了什么事。

简单来说,jQuery.fn下的函数,绝大部分是一个each的调用,所谓each,自然是对选择出来的元素进行了遍历,并对某个元素进行了指定的操作。那么看看上面一段代码,进行了多少的遍历,在此就假设只选择了120行,每一行有6列,另加上1行的表头吧:

  1. 遍历th,添加headerClass,元素数为6。
  2. 遍历td,添加cellClass,元素数为6*120=720。
  3. 从所有tr中找出奇数的,需要对所有tr进行一次遍历,元素数为120。
  4. 遍历奇数的tr,添加evenRowClass,元素数为120/2=60。
  5. 从所有tr中找出偶数的,需要对所有tr进行一次遍历,元素数为120。
  6. 遍历偶数的tr,添加oddRowClass,元素数为120/2=60。
  7. 遍历所有th和td,添加text-align,元素数为120*6+6=726。
  8. 遍历所有tr,添加mouSEOver事件,元素数为120。
  9. 遍历所有tr,添加mouSEOut事件,元素数为120。
  10. 遍历所有tr,添加click事件,元素数为120。

为了方便,我们简单地假设,在遍历中访问一个元素耗时为10ms,那么这个函数一共用了多少时间呢?这个函数共遇上了2172个元素,耗时21720ms,即21秒,显然IE确实应该报脚本执行过久了。

基本优化

知道了效率低下的原因,要从根本上进行解决,自然要想方设法来合并循环,初略一看,按照上边代码中注释里的数字,至少以下几点是可以合并的:

  • 3和4可以合并为一次循环,从120+60+120+60变为120,减少了240。
  • 1、2和5可以合并为一次循环,从6+720+726变为726,减少了726。
  • 6、7、8可以合并为一次循环,从120+120+120变为120,减少了240。
  • 进一步的,3、4和6、7、8一样可以合并为一次循环,继续减少了120。

累加一下,我们一共减少了240+726+240+120=1326次元素操作,总计13260ms。在优化之后,我们的函数耗时变为21720-13260=8460ms,即8s。

注意选择器

到这里可能会有一个疑问,从表格的结构上来说,所有的th和td元素肯定都在tr之内,那么为什么不将1、2、5这三步的循环同样放到对tr的循环中,形成一个嵌套的循环,这样不是更加快速吗?

这里之所以没有这么做,主要有2个原因:

其一,无论将1、2、5这三者放在哪里,都不会减少对所有th和td元素的一次访问。

另一方面,$(‘th,td’)这个选择器,在sizzle中会被翻译成2次getElementsByTagName函数的调用,第一次获取所有 th,第二次获取所有td,然后进行集合的归并。由于getElementsByTagName是内置函数,在此可以认为该函数是不带循环的,即复杂度为 O(1),同样集合的归并使用Array的相关函数,是对内存的操作,复杂度同样为O(1)。

反之,如果在对tr元素的循环中再采用$(‘th,’td)这个选择器,则是在tr元素上调用2次getElementsByTagName,由于 无论在哪个元素上调用该函数,函数执行的时间是相同的,因此在循环tr时使用,反而多出了119*2次的函数调用,效率不升反降。

可见,对sizzle选择器的基本知识,也是帮助优化jQuery代码的很重要的一方面。

不要啥都让JavaScript来做

根据前面的基本的优化,已经将时间从21秒降到了8秒,但是8秒这个数字显然是无法接受的。

再进一步分析我们的代码,事实上,循环遍历是语言层面上的内容,其速度应该是相当快的。而针对每个元素所做的操作,是jQuery提供的函数,相比 遍历来说,才是占去大部分资源的主子。如果说遍历中访问元素用时是10ms的话,不客气地说执行一个addClass至少是100ms级别的消耗。

因此,为了进一步地优化效率,就不得不从减少对元素的操作入手。再仔细地回审代码,发现这个函数有着非常多的对样式的修改,其中至少包括了:

  • 给所有th加上class。
  • 给所有td加上class。
  • 给tr分奇偶行加上class。
  • 给所有th和td加上一个text-align样式。

而事实上我们知道,CSS本身就拥有子代选择器,而浏览器原生对CSS的解析,效率远远高于让JavaScript去给元素一一加上class。

所以,如果对CSS是可控的,那么这个函数就不应该拥有headerClass、cellClass这两个配置项,而是尽可能地在CSS中进行配置:

.beautiful-table th { /* headerClass的内容 */ }
.beautiful-table td { /* cellClass的内容 */ }

再者,对于tr的奇偶行样式,在部分浏览器下可以使用:nth-child伪类来实现,这方面可以利用特性探测,仅在不支持该伪类的浏览器中使用addClass添加样式。当然如果你仅仅想对IE系列进行优化的话,这一条可以忽略了。

对于:nth-child伪类的探测,可以用以下的思路来进行:

  1. 创建一个stylesheet,再创建一条规则,如#test span:nth-child(odd) { display: block; }。
  2. 创建相应的HTML结构,一个id为test的div,内部放置3个span。
  3. 将stylesheet和div一同加入的DOM树中。
  4. 查看第1和第3个span的运行期display样式,如果是block,则表明支持该伪类。
  5. 删除创建的stylesheet和div,别忘了缓存探测的结果。

最后,对于给所有th和td元素添加text-align样式,也是可以通过css进行优化的。既然不知道添加的是哪个align,那么就多写几个样式:

/* CSS样式 */
.beautiful-table-center th,.beautiful-table-center td { text-align: center !important; }
.beautiful-table-right th,.beautiful-table-right td { text-align: right !important; }
.beautiful-table-left th,.beautiful-table-left td { text-align: left !important; }

/* javascript */
table.addClass('beautiful-table-' + options.align);

当然,上面所说的优化,是建立在对CSS有控制权的情况下的,如果本身无法接触到CSS样式,比如这是一个通用的插件函数,会被完全无法控制的第三方使用,那么怎么办呢?也不是完全没有办法:

  1. 去找页面里的所有CSS规则,比如document.styleSheets。
  2. 遍历所有规则,把配置项中的headerClass、cellClass等拿出来。
  3. 提取需要的几个class中的所有样式,再自己组装成新的选择器,如beautiful-table th。
  4. 使用创建出来的选择器,生成新的stylesheet,加入到DOM树中。
  5. 那么只给table加上beautiful-table这个class就搞定了。

当然上面的做法其实也蛮消耗时间的,毕竟又要遍历stylesheet,又要创建stylesheet。具体是不是对效率提升有很大的帮助,则依据页面的规模会有不同的效果,是否使用就要看函数设计人员的具体需求了,这里也就是提一种策略。

总的来说,通过尽可能少地执行JavaScript,将更多的样式化的任务交给CSS,则浏览器的渲染引擎来完成,又可以进一步地优化该函数,假设 对addClass、css的调用需要100ms的话,此次优化直接消灭了原有120+726=846次的操作,节约了84600ms的时间(当然有夸张 的成分,但是对整个函数的消耗来说,这个确实是很大的一块)。

最后的补充

这篇文章,仅仅是想在jQuery的各个实现的层面上来进行优化,只涉及到了对jQuery整个运行过程的分析、细节介绍和优化方向,并没有提到一些基本之基本的优化方法,比如:

  • 先将整个table从DOM树中移除,完成所有的操作之后再放回DOM,减少repaint。
  • 将mouSEOver和mouseout改为mouseenter和mouseleave,减少因为下正确的事件冒泡模型导致的重复的事件函数的执行。
  • 对于th、td之类单纯元素的选择,优先考虑使用原生的getElementsByTagName,消灭sizzle分析选择器的时间。

最后,这篇文章只是想说明,对于前端开发人员,虽然浏览器可能是个黑盒,但是很多框架、工具、库都是开放的,在使用之前如果可以进行一定程度的了解,必然有助于个人的技术提升和最终产品的质量优化,“知其然而不知其所以然”是非常忌讳的情况。

[转载]10个有用的jquery 图片插件

mikel阅读(940)

[转载]10个有用的jquery 图片插件 – jqpeng的技术记事本 – 博客园.

JQuery的灵活性为我们所熟知并热爱。

给人映象最深的JQuery应用通常与图片相关。

事实上,你可以借助JQuery来处理图片达到给你的项目增添令人惊奇的功能!

这里筛选了10个非常有用的jQuery 插件,在你的下一个项目中使用它们吧!

1、Slides
image

Slides是一个简单的SlideShow插件。包含循环播放,自动播放,过渡动画,图片预加载,自动生成页码等功能。

2、Face Detection

image

正如它的名字,这个插件用来标示图片中的人物

3、AviaSlider

image

AviaSlider 是一个包含唯一过渡效果的Slide插件

4、Fullscreenr

image

你想在你的网站中的背景图片始终填满屏幕并且保持纵横比吗?那么,This plugin does that.

5、Slidy

image

jQuery Slidy is a plugin that generates a customizable transitions automatically.

6、MobilyNotes

image

MobilyNotes 是一款轻量级的(2KB) jQuery 插件,让你的图片显示为层叠的效果

7、jQuery Easy Slides

image

Easy Slides 同样是一款轻量级的Slide插件(JavaScript CSS 加一起就2.1kb),并且易于使用

8、Booklet

image

Booklet is a jQuery plugin for displaying images and more in a book format with a turning page effect.

9、MobilySelect

jquery image plugins

MobilySelect is jQuery plugin (2kB) that replaces one collection of items with another.

10、Pikachoose

image

Pikachoose同样是一个轻量级的Jquery plugin,上面的配图清楚地展示了其功能

原文地址:http://webdesignledger.com/freebies/10-useful-jquery-plugins-for-images

[转载]ASP.NET MVC 3 中文版正式释出上线

mikel阅读(955)

[转载]ASP.NET MVC 3 中文版正式释出上线 – Nana的荔枝园 – 博客园.

今天在微软(中国)下载中心首页最新下载栏目中已经提供了 ASP.NET MVC 3 中文版 的下载链接。

除了 ASP.NET MVC 3 以外,从前几天开始微软就提供了另外几款免费 Web 平台产品的中文版下载,它们分别是:

注:

安装 WebMatrix 以前请确保已经安装了 WebPIIIS 7.5 ExpressWeb Deploy

Razor 引擎的 Visual Studio 支持是包含在 ASP.NET MVC 3 中的,如果希望在编辑 Razor 模板时利用到 Visual Studio 的便利功能,就需要安装 ASP.NET MVC 3;但是 Razor 文档本身可以用任何文本编辑器进行编辑,只要安装了 Razor 引擎的独立安装版本,任何现有的 ASP.NET 网站都可以使用 Razor 文档(不包括使用 CodeBehind 模式的『ASP.NET 应用程序』项目——这类的项目应该使用 ASPX 文档)。

另外,Visual Studio 2010 Service Pack 1 应该会在几个星期以后推出

>>>>>>> And can you tell when we will get Visual Studio 2010 Service Pack 1?

This will ship in a few more weeks.

Hope this helps,

Scott

[转载]SQL Server 监控系列 —— 二

mikel阅读(895)

[转载]SQL Server 监控系列 —— 二

监控前言

上一节我们提到了MSSQL的基于SQL Event的监控,但是有些时候我们需要更加详细、适用于调优排错的监控。SQL Server内部运行的可见性是的查询调整、优化和综合排查成为可能!这一节主要和大家说说SQL Server跟踪(SQL Server Profile)的一些监控方式和途径。

使用场景

记得某次给一家公司调优的时候,负责人发给我一堆业务的T-SQL脚本,我面对海量脚本还是从容,虽然不了解内部复杂的业务,但是我们得专注问题的关键 “慢”,我们根据查询的“慢”把他们筛选出来,一一调式优化,不就迅速解决问题吗?三天后,负责人含泪握着我的手,哥们辛苦了,查询响应得到了质的改善。

跟踪提供者

SQL Server 为我们两者提供跟踪的方式:一种是一个物理文件(可保存在本机或者UNC网络路径),一种是行集。对于后者大家应该比较熟悉

image

这个工具在 SSMS 的 工具 –> SQL Profile

AB490696-8C76-4819-A08D-1D14E3E828BA

详细的我暂时不介绍,先说说两者的区别和类同点 DIFFAndSame(行集,文件提供者)。

  • 两者都是用类似Buffer来保存当前的事件数据,很明显是为了减少IO的压力,这样可以不阻塞和尽量不遗漏 事件数据,当Buffer 到达一定量时候可能才会Flush到磁盘或者发送到网络的终端(客户端)显示监控行集。
  • 物理文件保存监控结果的方式的重要保证不能遗漏任何事件,一旦IO降速的时候,可能会影响到整个T-SQL的执行情况。
    SELECT * FROM sys.dm_os_wait_stats WHERE wait_type IN ('SQLTRACE_LOCK','IO_COMPLETION');
    我使用这个语句来监控TRACE 和IO 完成对我当前机器的影响,我的某个客户的IO情况:
wait_type waiting_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_ms
IO_COMPLETION 66030898 24377499 3634 418960
SQLTRACE_LOCK 12007 175943 1001 1281

因为我进行了大量的过滤,因此这个值还是能够接受的,影响不是特别大。

  • 行结果集的方式,其实也是我们最熟悉的,就是使用SQL Server Profile监控GUI 直接展现给我们看到的。但是,我是非常不建议使用的,首先如果Buffer满了,它有一定的延迟,可能会抛弃事件已 清空缓存区继续接受事件,而事件没有发送到Client,也没有写到物理文件,自然就丢失了。比如,SQL Server Profile 在DB服务器进行监控,因为高负载的机器再用来展示,很有可能就会丢失事件,另外物理文件方式,其实是接受一个足够大的Buffer,进行的大块写操作, 性能是优于行集的。

image(行集)

保密性原则

SQL Server的安全特性会自动过滤 包含隐私的数据,比如密码。我在我的SSMS中执行了如下的语句:

EXEC sp_password 'pp','pp1','sa';
这是修改sa帐号密码的系统sp,我打开了SQL Server Profile –> 选择了T-SQL 监控模版 
image
然后执行上面的存储过程,监控结果:
image

监控结果:–*sp_password—————————-

SQL Server Profile

使用SQL Server Profile GUI工具还是很多优势,首先是减少了我们监控的复杂性,可以款速的建立监控,在跟踪属性中,可以可以选择MSSQL为我们提供的模版,包括常用的T-SQL、T-SQL Duration、T-SQL Locks模版分别监控当前DB运行的所有查询,所有查询的耗时、所有的锁定状态。

跟踪属性 –> 选择事件选择 我们可以选择自己需要的事件,所有的事件在MSDN 都有定义->单击列筛选器 可以自定义过滤,排序噪点干扰因素

image(我随便选择了一个耗时 = 500 微妙的过滤条件)

其他的模版大家可以自己看看MSDN 手册,自己尝试一下:SQL Server 2008 R2 本机  MSDN

服务器端跟踪和物理方式收集

SQL Server Profile 只是对一些存储过程的封装,我更倾向于,自己定义常用的脚本,将监控结果保存在本机,用来大量的分析和存档。

当然涉及4个存储过程,虽然设置过滤的脚本非常麻烦,但是SQL Server Profile 可以利用 文件->导出 可以导出监控脚本意味着,我们不需要编写复杂的T-SQL 脚本,不过还是建议大家熟悉这几个存储过程:

  • sp_trace_create 定义跟踪 ,创建的跟踪会在sys.traces查询的到。
  • s_trace_setevent 设置监控事件
  • sp_trace_setfilter 设置过滤
  • sp_trace_setstatus 设置跟踪的状态  常用的是  sp_trace_setstatus @traceid,0 停止功能 、sp_trace_setstatus @traceid,2 移除跟踪,这将导致sys.traces最终查询不到该跟踪

其实整个跟踪还是比较简单的。我这里有一个常用的脚本:

用来 监控超过指定秒数 和 数据库 的 批处理和存储过程 语句(超过5MB的文件,会执行ROLLOVER,根据文件名在后面添加类似_1,_2.trc的跟踪结果):

CREATE PROC [dbo].[sp_trace_sql_durtion]
    @DatabaseName nvarchar(128),
    @Seconds bigint,
    @FilePath nvarchar(260)
AS
BEGIN
DECLARE @rc int,@TraceID int,@MaxFileSize bigint;
SET @MaxFileSize = 5;

EXEC sp_trace_create @TraceID OUTPUT,2,@FilePath,@MaxFileSize,NULL;

IF @rc != 0
    RETURN;

DECLARE @On bit;
SET @On = 1;

EXEC sp_trace_setevent @TraceID,10,35,@On;
EXEC sp_trace_setevent @TraceID,10,1,@On;
EXEC sp_trace_setevent @TraceID,10,13,@On;
EXEC sp_trace_setevent @TraceID,41,35,@On;
EXEC sp_trace_setevent @TraceID,41,1,@On;
EXEC sp_trace_setevent @TraceID,41,13,@On;

SET @Seconds = @Seconds * 1000000;

EXEC sp_trace_setfilter @TraceID,13,0,4,@Seconds;

IF @DatabaseName IS NOT NULL
    EXEC sp_trace_setfilter @TraceID,35,0,0,@DatabaseName

EXEC sp_trace_setstatus @TraceID,1
SELECT TraceID = @TraceID;

END
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }参数非常的明了,数据库名称、执行事件超过多少秒、保存的路径。

当我们运行这个脚本一段事件以后,可以快速的发现大量耗时的T-SQL,我们可以通过

SELECT * FROM fn_trace_gettable(N'监控文件路径',1);
来查看行方式的结果。
同样的富有创造力的读者可以自己创建监控锁定,监控死锁等方式保存文件,但是我的建议是尽可能的减少噪音,也就是说我们要达到什么目地就
建立什么功能,这样才能将大问题细化解决。
在《Microsfot SQL Server 2005 技术内幕: T-SQL 程序设计》 中有一个正则,用来将类似的语句全部组合成,只有参数形式替换具体值
的SQL CLR,但是我认为那个正则还有bug,等我空了给大家写一个,自己也能使用的更完善。
监控异常
    在上个系列中,讲述了具体的SQL Event抓去的异常,可以及时通知,但是具体的异常信息,并不是特别详细。因此我们可以选择事件中的
Error来添加有关T-SQL批处理和SP的所有异常,用于分析,这个跟踪非常有利于我们监控一些异常情况!!!
我创建了一个跟踪的脚本,和上面的跟踪事件的脚本一样,超过5MB RollOver。
    我们要定期的执行这个跟踪,虽然不建议长期开启,但是定期监控处理异常是有利我们系统更加长时间运作的。
CREATE PROC [dbo].[sp_trace_sql_exception]
    @FilePath nvarchar(260)
AS
DECLARE @rc int,@TraceID int,@Maxfilesize bigint
SET @maxfilesize = 5


EXEC @rc = sp_trace_create @TraceID output, 2, @FilePath, @Maxfilesize, NULL
IF (@rc != 0)
    RETURN;

DECLARE @on bit
SET @on = 1
EXEC sp_trace_setevent @TraceID, 33, 1, @on
EXEC sp_trace_setevent @TraceID, 33, 14, @on
EXEC sp_trace_setevent @TraceID, 33, 51, @on
EXEC sp_trace_setevent @TraceID, 33, 12, @on
EXEC sp_trace_setevent @TraceID, 11, 2, @on
EXEC sp_trace_setevent @TraceID, 11, 14, @on
EXEC sp_trace_setevent @TraceID, 11, 51, @on
EXEC sp_trace_setevent @TraceID, 11, 12, @on
EXEC sp_trace_setevent @TraceID, 13, 1, @on
EXEC sp_trace_setevent @TraceID, 13, 14, @on
EXEC sp_trace_setevent @TraceID, 13, 51, @on
EXEC sp_trace_setevent @TraceID, 13, 12, @on

DECLARE @intfilter int,@bigintfilter bigint;

EXEC sp_trace_setstatus @TraceID, 1

SELECT TraceID=@TraceID
GOTO finish

ERROR:
SELECT ErrorCode=@rc

FINISH:

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }定期执行吧,同志们,找异常。。。

默认跟踪和黑盒跟踪

在sys.traces中的TraceID = 1的跟踪是SQL Server 默认跟踪,这个跟踪比较轻量级,一般监控服务器的启用停止,对象的创建和删除,日志和数据文件自动增长以及其他数据库的变化。(监控那些没事删错了表的 人,是最好的,当然前提不要都使用一个帐号!)

可以通过

EXEC sp_configure ‘default trace enabled’,0;

RECONFIGURE WITH OVERRIDE;

来关闭默认跟踪。

黑盒跟踪,就是可以帮助我们诊断数据库没事自个奔了的异常,在MSDN 搜索sp_create_trace的时候应该也发现了

image

的选项,那么我们也能创建一个类似的存储过程来快速的创建黑盒跟踪,帮助我们诊断一些异常!

CREATE PROCEDURE sp_trace_blackbox
    @FilePath nvarchar(260)
AS
BEGIN
    DECLARE @TraceID int,@MaxFileSize bigint
    SET @MaxFileSize = 25;
    EXEC sp_trace_create @TraceID OUTPUT,8,@FilePath,@MaxFileSize
    EXEC sp_trace_setstatus @TraceID,1;

END

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas,”Courier New”,courier,monospace; background-color: rgb(255, 255, 255); }.csharpcode pre { margin: 0em; }.csharpcode .rem { color: rgb(0, 128, 0); }.csharpcode .kwrd { color: rgb(0, 0, 255); }.csharpcode .str { color: rgb(0, 96, 128); }.csharpcode .op { color: rgb(0, 0, 192); }.csharpcode .preproc { color: rgb(204, 102, 51); }.csharpcode .asp { background-color: rgb(255, 255, 0); }.csharpcode .html { color: rgb(128, 0, 0); }.csharpcode .attr { color: rgb(255, 0, 0); }.csharpcode .alt { background-color: rgb(244, 244, 244); width: 100%; margin: 0em; }.csharpcode .lnum { color: rgb(96, 96, 96); }我这里提供@FilePath = NULL参数,这个默认就保存在SQL Server的数据文件夹中。

结尾

这里详细的描述了SQL Server Trace 的各种功能特性,有兴趣的朋友可以深入到MSDN研究监控,我这是也只是一笔带过,也参考了MSDN 和《Microsoft SQL Server 2005调优》那本书,下面的监控可能和大家讲述 DDL触发器监控,C2审核以及SQL Server的事件通知(涉及的Service Broker我会开一个系列和大家详细说说Service Broker),最后的结束可能就是说说2008的数据收集监控,大家期待吧。休息~