[转载]SQL Server 2008中的CTE递归查询

mikel阅读(941)

[转载]SQL Server 2008中的CTE递归查询 – xfrog – 博客园.

今天基本搞清楚SQL Server中递归查询的实现方式,So,先记录下来。不过呢,个人觉得SQL Server的递归查询相对于Oracle中的递归查询更加难以理解困惑
从SQL Server 2005开始,我们可以直接通过CTE来支持递归查询,这对查询树形或层次结构的数据很有用。CTE即公用表表达式,虽然不恰当,但你可以将它看做成一个临时命名的结果集合。
我们先建立一个示例表,名称为MENU,表示菜单的层次结构:

显示行号 复制代码 SQL
  1. CREATE TABLE MENU 
  2.  (
  3.     name nvarchar(50) NOT NULL PRIMARY KEY,
  4.     senior nvarchar(50) NULL
  5. );
  6.  
  7.  INSERT INTO MENU values
  8.     ('文件',NULL),
  9.     ('新建','文件'),
  10.     ('项目','新建'),
  11.     ('使用当前连接查询','新建');
.src_container { background-color: rgb(231, 229, 220); width: 99%; overflow: hidden; margin: 12px 0pt ! important; padding: 0px 3px 3px 0px; }.src_container .titlebar { background-color: rgb(212, 223, 255); border-width: 1px 1px 0pt; border-style: solid solid none; border-color: rgb(79, 129, 189) rgb(79, 129, 189) -moz-use-text-color; padding: 3px 24px; margin: 0pt; width: auto; line-height: 120%; overflow: hidden; text-align: left; font-size: 12px; }.src_container .toolbar { display: inline; font-weight: normal; font-size: 100%; float: right; color: rgb(0, 0, 255); text-align: left; overflow: hidden; }.toolbar span.button { display: inline; font-weight: normal; font-size: 100%; color: rgb(0, 0, 255); text-align: left; overflow: hidden; cursor: pointer; }.src_container div.clientarea { background-color: white; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; height: auto; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,courier,monospace,serif; }.src_container ol.mainarea { padding: 0pt 0pt 0pt 52px; margin: 0pt; background-color: rgb(247, 247, 255) ! important; }.number_show { padding-left: 52px ! important; list-style: decimal outside none ! important; }.number_show li { list-style: decimal outside none ! important; border-left: 1px dotted rgb(79, 129, 189); }.number_hide { padding-left: 0px ! important; list-style-type: none ! important; }.number_hide li { list-style-type: none ! important; border-left: 0px none; }ol.mainarea li { display: list-item ! important; font-size: 12px ! important; margin: 0pt ! important; line-height: 18px ! important; padding: 0pt 0pt 0pt 0px ! important; background-color: rgb(247, 247, 255) ! important; color: rgb(79, 129, 189); }ol.mainarea li pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap ol.mainarea li pre { white-space: pre-wrap; word-wrap: break-word; }ol.mainarea li pre.alt { background-color: rgb(247, 247, 255) ! important; }表示的菜单层次如下:

文件
新建
项目
使用当前连接查询

OK,先看CTE的语法:
WITH CTE名称(字段列表)
AS
(
查询语句
)
例如:
WITH lmenu(name,senior)
as
(
SELECT name,senior from menu
)

我们定义了一个名称为lmenu的CTE,这样我们后续即可直接使用lmenu来查询,如:
SELECT * FROM lmenu

如果我们在定义CTE的查询语句中直接引用CTE表本身,则会形成递归查询,当然递归查询具有自己的特殊结构,下面的SQL通过递归查询获取每个菜单的层次深度:

显示行号 复制代码 SQL
  1. WITH lmenu(name,senior,level) as
  2.  (
  3.     SELECT NAME,SENIOR,0 level FROM MENU WHERE SENIOR IS NULL
  4.     UNION ALL
  5.     SELECT A.NAME,A.SENIOR,b.level+1 FROM MENU A,lmenu b
  6.     where a.senior = b.name
  7. )
  8. SELECT *  from lmenu

.src_container { background-color: rgb(231, 229, 220); width: 99%; overflow: hidden; margin: 12px 0pt ! important; padding: 0px 3px 3px 0px; }.src_container .titlebar { background-color: rgb(212, 223, 255); border-width: 1px 1px 0pt; border-style: solid solid none; border-color: rgb(79, 129, 189) rgb(79, 129, 189) -moz-use-text-color; padding: 3px 24px; margin: 0pt; width: auto; line-height: 120%; overflow: hidden; text-align: left; font-size: 12px; }.src_container .toolbar { display: inline; font-weight: normal; font-size: 100%; float: right; color: rgb(0, 0, 255); text-align: left; overflow: hidden; }.toolbar span.button { display: inline; font-weight: normal; font-size: 100%; color: rgb(0, 0, 255); text-align: left; overflow: hidden; cursor: pointer; }.src_container div.clientarea { background-color: white; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; height: auto; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,courier,monospace,serif; }.src_container ol.mainarea { padding: 0pt 0pt 0pt 52px; margin: 0pt; background-color: rgb(247, 247, 255) ! important; }.number_show { padding-left: 52px ! important; list-style: decimal outside none ! important; }.number_show li { list-style: decimal outside none ! important; border-left: 1px dotted rgb(79, 129, 189); }.number_hide { padding-left: 0px ! important; list-style-type: none ! important; }.number_hide li { list-style-type: none ! important; border-left: 0px none; }ol.mainarea li { display: list-item ! important; font-size: 12px ! important; margin: 0pt ! important; line-height: 18px ! important; padding: 0pt 0pt 0pt 0px ! important; background-color: rgb(247, 247, 255) ! important; color: rgb(79, 129, 189); }ol.mainarea li pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap ol.mainarea li pre { white-space: pre-wrap; word-wrap: break-word; }ol.mainarea li pre.alt { background-color: rgb(247, 247, 255) ! important; }结果:

name                                               senior                                             level
————————————————– ————————————————– ———–
文件                                                 NULL                                               0
新建                                                 文件                                                 1
使用当前连接查询                               新建                                                 2
项目                                                 新建                                                 2

注意查询定义语句,它由两条查询语句构成,其中

SELECT NAME,SENIOR,0 level FROM MENU WHERE SENIOR IS NULL

称为定位成员,SQL Server通过此语句来判断是否继续进行递归。
语句

SELECT A.NAME,A.SENIOR,b.level+1 FROM MENU A,lmenu b
where a.senior = b.name

称之为递归成员,其特征为from子句中引用了CTE对象自身。
递归CTE具有一些限制条件(引自MSDN):

至少有一个定位点成员和一个递归成员,当然,你可以定义多个定位点成员和递归成员,但所有定位点成员必须在递归成员的前面
定位点成员之间必须使用UNION ALL、UNION、INTERSECT、EXCEPT集合运算符,最后一个定位点成员与递归成员之间必须使用UNION ALL,递归成员之间也必须使用UNION ALL连接
定位点成员和递归成员中的字段数量和类型必须完全一致
递归成员的FROM子句只能引用一次CTE对象
递归成员中不允许出现下列项
SELECT DISTINCT
GROUP BY
HAVING
标量聚合
TOP
LEFT、RIGHT、OUTER JOIN(允许出现 INNER JOIN)
子查询

CTE递归查询的执行方式:
递归的终止依赖于定位点成员的,如果理解了这一点,也就理解了递归查询的执行方式。
我们来看上例的执行执行过程:

SELECT * FROM lmenu

这条语句进入递归查询

SELECT A.NAME,A.SENIOR,b.level+1 FROM MENU A,lmenu b
where a.senior = b.name

作为最外层的语句,显然递归的第一层应该根据MENU表的记录来循环(如果查询执行计划,这表示一个嵌套循环),假设menu表中查询出的记录顺序如下:

name                                               senior
————————————————– ————————————————–
文件                                                 NULL
新建                                                 文件
使用当前连接查询                               新建
项目                                                 新建

第一条记录:
首先判断是否进入递归,由于 文件包含在定位点成员结果集中,不符合递归条件,所以不进入递归,直接返回从定位点成员集合中返回记录:

select name,senior,0 level from menu where senior is null and name=’文件’

name                                               senior                                             level
————————————————– ————————————————– ———–
文件                                                 NULL                                               0
第二条记录:
即NAME = ‘新建’, 定位点成员结果集中没有该记录,将进入递归:
将当前行的值带入递归成员:

SELECT A.NAME,A.SENIOR,b.level+1 level FROM MENU A,lmenu b
where a.senior = b.name
AND a.senior = ‘文件’
AND a.name=’新建’

由于递归的关联条件是a.senior = b.name,所以b.name=’文件’,以此条件进入下级递归,这实际上就是第一条记录的情况,由于name=’文件’符合定位点条件,所以将终止递 归,如果我们用子查询来替换掉lmenu递归成员,第二条记录的查询语句实际为:

显示行号 复制代码 SQL
  1. SELECT a.name,a.senior,b.level+1 from menu a, (
  2.   select name,senior,0 level  from menu where senior is null and name='文件'
  3. ) b
  4. where a.senior=b.name
  5.     and a.senior = '文件'
  6.     and a.name='新建'

.src_container { background-color: rgb(231, 229, 220); width: 99%; overflow: hidden; margin: 12px 0pt ! important; padding: 0px 3px 3px 0px; }.src_container .titlebar { background-color: rgb(212, 223, 255); border-width: 1px 1px 0pt; border-style: solid solid none; border-color: rgb(79, 129, 189) rgb(79, 129, 189) -moz-use-text-color; padding: 3px 24px; margin: 0pt; width: auto; line-height: 120%; overflow: hidden; text-align: left; font-size: 12px; }.src_container .toolbar { display: inline; font-weight: normal; font-size: 100%; float: right; color: rgb(0, 0, 255); text-align: left; overflow: hidden; }.toolbar span.button { display: inline; font-weight: normal; font-size: 100%; color: rgb(0, 0, 255); text-align: left; overflow: hidden; cursor: pointer; }.src_container div.clientarea { background-color: white; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; height: auto; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,courier,monospace,serif; }.src_container ol.mainarea { padding: 0pt 0pt 0pt 52px; margin: 0pt; background-color: rgb(247, 247, 255) ! important; }.number_show { padding-left: 52px ! important; list-style: decimal outside none ! important; }.number_show li { list-style: decimal outside none ! important; border-left: 1px dotted rgb(79, 129, 189); }.number_hide { padding-left: 0px ! important; list-style-type: none ! important; }.number_hide li { list-style-type: none ! important; border-left: 0px none; }ol.mainarea li { display: list-item ! important; font-size: 12px ! important; margin: 0pt ! important; line-height: 18px ! important; padding: 0pt 0pt 0pt 0px ! important; background-color: rgb(247, 247, 255) ! important; color: rgb(79, 129, 189); }ol.mainarea li pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap ol.mainarea li pre { white-space: pre-wrap; word-wrap: break-word; }ol.mainarea li pre.alt { background-color: rgb(247, 247, 255) ! important; }name                                               senior                                             level
————————————————– ————————————————– ———–
新建                                                 文件                                                 1

第三条记录:
NAME=’使用当前连接查询’,同样不符合定位点条件,将进入递归:

SELECT A.NAME,A.SENIOR,b.level+1 FROM MENU A,lmenu b
where a.senior = b.name
AND a.senior = ‘新建’
AND a.name = ‘使用当前连接查询’

同样,代入当前记录条件,下级递归b.name=’新建’,由于’新建’还不符合定位点条件,所以还将继续递归,及lmenu b表示子查询:

select c.name,c.senior,d.level+1 level from menu c,lmenu d
where c.senior = d.name
and c.name = ‘新建’
and c.senior = ‘文件’

替换成上述语句后,d.name=’文件’,将再次判断是否需要继续递归,由于’文件’符合终止递归条件,所以将终止递归。
我们用子查询表示第三条记录的递归过程如下:

显示行号 复制代码 SQL
  1. SELECT a.name,a.senior,b.level+1 level FROM menu A,(
  2.         select c.name,c.senior,d.level+1 level from menu c,(
  3.           select name,senior,0 level from menu where senior is null and name='文件'
  4.     ) d
  5.     where c.senior = d.name
  6.         and c.name = '新建'
  7.         and c.senior = '文件'   
  8. ) b
  9. where a.senior = b.name
  10.     and a.senior = '新建'
  11.     and a.name = '使用当前连接查询'

.src_container { background-color: rgb(231, 229, 220); width: 99%; overflow: hidden; margin: 12px 0pt ! important; padding: 0px 3px 3px 0px; }.src_container .titlebar { background-color: rgb(212, 223, 255); border-width: 1px 1px 0pt; border-style: solid solid none; border-color: rgb(79, 129, 189) rgb(79, 129, 189) -moz-use-text-color; padding: 3px 24px; margin: 0pt; width: auto; line-height: 120%; overflow: hidden; text-align: left; font-size: 12px; }.src_container .toolbar { display: inline; font-weight: normal; font-size: 100%; float: right; color: rgb(0, 0, 255); text-align: left; overflow: hidden; }.toolbar span.button { display: inline; font-weight: normal; font-size: 100%; color: rgb(0, 0, 255); text-align: left; overflow: hidden; cursor: pointer; }.src_container div.clientarea { background-color: white; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; height: auto; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,courier,monospace,serif; }.src_container ol.mainarea { padding: 0pt 0pt 0pt 52px; margin: 0pt; background-color: rgb(247, 247, 255) ! important; }.number_show { padding-left: 52px ! important; list-style: decimal outside none ! important; }.number_show li { list-style: decimal outside none ! important; border-left: 1px dotted rgb(79, 129, 189); }.number_hide { padding-left: 0px ! important; list-style-type: none ! important; }.number_hide li { list-style-type: none ! important; border-left: 0px none; }ol.mainarea li { display: list-item ! important; font-size: 12px ! important; margin: 0pt ! important; line-height: 18px ! important; padding: 0pt 0pt 0pt 0px ! important; background-color: rgb(247, 247, 255) ! important; color: rgb(79, 129, 189); }ol.mainarea li pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap ol.mainarea li pre { white-space: pre-wrap; word-wrap: break-word; }ol.mainarea li pre.alt { background-color: rgb(247, 247, 255) ! important; }name                                               senior                                             level
————————————————– ————————————————– ———–
使用当前连接查询                                           新建                                                 2

第四条记录与第三条记录的递归层次完全一样。

[转载]如何:创建指向Web的快捷方式

mikel阅读(971)

[转载]如何:创建指向Web的快捷方式 – nGn – 博客园.

如何:创建指向Web的快捷方式

WiX支持在执行安装时创建指向Internet站点的快捷方式。本例中引用一个必须的实用程序库并添加一个Internet快捷方式到你的安装包。这里假定你已经阅读过如何:在开始菜单中创建快捷方式

第一步:添加WiX实用程序扩展库到你的工程

WiX对创建Internet快捷方式的支持被包括在一个WiX实用程序扩展库中,所以首先应该将其添加到工程中以备使用。如果使用命令行方式你需要添加下面的参数到candle和light命令后面。

-ext WiXUtilExtension

如果在Visual Studio中使用WiX,你可以通过“添加引用”对话框添加扩展库。

  1. 在Visual Studio中打开你的WiX工程
  2. 右键单击解决方案资源管理器中你的工程,选择添加引用…
  3. 从列表中选择WixUtilExtension.dll程序集并且单击添加
  4. 关闭添加引用对话框

第二步:添加WiX实用程序扩展命名空间到你的工程

当扩展库添加到工程中以后,你需要添加实用程序扩展命名空间到你的工程中以便你可以访问相应的WiX元素。你需要编辑你工程中顶层的<Wix>元素添加下面的属性。

xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"

一个带有标准命名空间和实用程序扩展命名空间的完整的Wix元素应该看起来像这样:

<Wix xmlns=http://schemas.microsoft.com/wix/2006/wi
xmlns:util=http://schemas.microsoft.com/wix/UtilExtension>

第三步:添加Internet快捷方式到你的安装包中。

Internet快捷方式使用<Util:InternetShortcut>元素创建。下面的例子是添加一个InternetShortcut元素到一个已有的快捷方式创建示例中,示例是如何:在开始菜单中创建快捷方式中创建的。

<DirectoryRef Id="ApplicationProgramsFolder">
    <Component Id="ApplicationShortcut" Guid="PUT-GUID-HERE">
        <Shortcut Id="ApplicationStartMenuShortcut" 
                  Name="My Application Name"
                  Description="My Application Description"
                  Target="[APPLICATIONROOTDIRECTORY]MyApplication.exe"
                  WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
        <util:InternetShortcut Id="OnlineDocumentationShortcut"
                        Name="My Online Documentation"
                               Target="http://www.wixwiki.com/"/>
        <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
        <RegistryValue Root="HKCU" Key="Software\Microsoft\MyApplicationName" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
    </Component>
</DirectoryRef>

InternetShortcut被赋予了一个唯一的ID属性。in this case the application’s Start Menu folder.(求翻译,确定原文就是这样。) Name属性指定开始菜单中快捷方式的名称。Target属性指定快捷方式的目标地址。<DirectoryRef>元素是用来引用工程中已 定义的文件夹结构。通过引用ApplicationProgramsFolder文件夹,快捷方式将被安装到用户开始菜单的My Application Name目录中。

[转载]6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱

mikel阅读(986)

[转载]6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱 – 倪大虾 – 博客园.

引言

本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱。文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆;最后介绍值类型和引用类型,并说明一些有关它们的重要原理。

最后通过一个简单的示例代码说明装箱拆箱带来的性能损耗。

声明变量的内部机制

在.NET程序中,当你声明一个变量,将在内存中分配一块内存。这块内存分为三部分:1,变量名;2,变量类型;3,变量值。

下图揭示了声明一个变量时的内部机制,其中分配的内存类型依据你的变量类型。.NET中有两种类型的内存:栈内存和堆内存。在接下来的内容中,我们会了解到这两种类型的详细内容。

栈和堆

为了明白什么是栈和堆,先让我们看下下面示例代码的内部机制:

1 public void Method1(){
2 // Line 1
3 int i=4;
4 // Line 2
5 int y=2;
6 //Line 3
7 class1 cls1 = new class1();
8 }

这里一共有3行代码。让我们一下逐行看一下它们是如何执行的:

第1行:当这行代码执行时,编译器为它分配一小块栈内存。运行时栈负责提供程序所需的内存;

第2行:程序继续执行。如同名字一样,栈在第一块内存的顶部分配了一块内存。你也可以认为是模块或零件一块一块叠起来;

内存的分配与释放遵循后进先出(后进先出)逻辑,换句话说,内存只能在示例中i内存块的顶部分配或释放。

第3行:在第3行,我们创建了一个对象。当该行执行时,编译器在站上创建了一个指针,真实的对象存储在另一种叫“堆”的内存中。”堆”并不跟踪运行 内存,它更像一堆随时可以访问的对象。堆用于动态分配内存。这里需要着重说明的是引用指针是分配在栈上。声明Class1 cls1时并不会给Class1的实例分配内存,而是分配一个栈变量cls1(并设置为null),然后把它指向“堆”。

退出方法:当方法退出时,它释放了栈上所有内存变量。换句话说,栈上所有的”Int”变量都依据后进先出的逻辑被释放掉了。要注意,此时不会释放堆内存,这种内存稍后会被“垃圾收集器”释放。

现在可能会有很多朋友奇怪为什么要分配2种内存,而不是仅用一种内存。

如果仔细观察,你会发现基本类型并不复杂,他们值包含简单的值,如i=0。对象数据类型很复杂,它们会引用其它对象或基本类型。换句话说,它要 保持其它多种多样的引用,而每种类型必须存在内存中。对象类型需要动态内存而基本类型需要静态内存。如果需要分配动态内存,那么就分配到堆上;反之在栈 上。

值类型与引用类型

现在我们明白了栈和堆,接下来看值类型和引用类型。值类型的数据和内存在同一个位置,而引用类型是一个指向内存的指针。

下面示例是一个整形数据类型变量i被赋给另一个整形数据类型变量j。它们的内存值都分配在栈上。当我们把一个int值分配给另外一个int值时,需要创建一个完全不同的拷贝。换句话说,你可以改变其中任何一个而不会影响另外一个。这种数据类型被称为值类型。 当我们创建一个对象,并把一个对象赋给另外一个对象时,它们的指针指向相同的内存(如下图,当我们把obj赋给obj1时,它们指向相同的内存)。换句话说,我们改变其中一个,会影响到另外一个,这种类型称为引用类型。

那么那种类型是值类型和引用类型呢?

在.NET中,依据数据类型,变量被分配到堆或栈上。“string”和”Object”是引用类型,其他基本类型被分配到栈上,是值类型,如下图:

装箱与拆箱

通过上面学习,我们学到了很多有用的东西,其中最有用的是明白了当把数据从栈移动到 堆上时会有性能损失。如下图实例,当我们把一个值类型装箱为引用类型时,数据从栈移动到堆上。反之,数据从堆移动到栈上。这种在堆和栈之间的移动带来了性 能的损失。数据从值类型转变为引用类型的过程称为“装箱”,反之为“拆箱”。

如果编译上面的代码,在ILDASM中看IL代码就会发下如何进行装箱拆箱操作的,如下:

装箱拆箱的性能影响

为了揭示装箱拆箱如何影响性能,我们把下面代码运行10000次。一个函数有装箱操作, 另一个只有简单代码。我们用简单的计时器看它们的运行时间。装箱函数耗时 3542 MS,无装箱操作的耗时2477MS。这说明在实际项目中,除非必须,否则应避免装箱,拆箱操作。

备注:

最近在CodeProject上看到<6 important .NET concepts: – Stack, heap, Value types, reference types, boxing and Unboxing>一文,个人觉得非常好,所以就翻一下给不想看英文的同学。由于能力有限,翻译的不好,望大家多多包涵。

[转载]SQL Server 2005 Express附加数据库为“只读”的解决方法

mikel阅读(1076)

[转载]SQL Server 2005 Express附加数据库为“只读”的解决方法 – 林子之大.net笔记 – 博客园.

SQL Server 2005 Express 上附加从另外一台电脑Copy过来的数据库后,数据库为“只读”。

解决办法:
打开 SQL Server Configuration Manager, 打开SQL Server SQLEXPRESS 的属性

在内置帐号处,把“网络服务”改成“本地系统”,重新启动SQL Server 2005 Express 后,再附加数据库一切正常。

总结:之所以附加上的数据库为“只读”,是因为启动SQL Server 的默认的启动帐号“网络服务”对所附加(Attach)的数据库文件的权限不够造成的。

[转载]Flex数据访问:WebService

mikel阅读(1070)

[转载]Flex数据访问:WebService – 无风 – 博客园.

WebService组件用于访问SOAP Web服务,此类服务时带有方法的软件模块,Web服务方法通常称为“操作(option)”,操作可以带参数(requet)。Web服务接口通过 Web 服务描述语言 (WSDL) 进行定义。通过 Web 服务提供的标准相容方式,在不同平台上运行的软件模块可以相互交互。

Flex 支持格式设置为 SOAP 消息且通过 HTTP 传输的 Web 服务请求和结果。SOAP 提供基于 XML 格式的定义,用于在 Web 服务客户端(如使用 Flex 构建的应用程序)和 Web 服务之间交换结构化和类型化信息。

在.NET和Flex的数据交互可以通过Web Services访问string,object,datatable,List<>,ArrayList等。

.NET和Flex的数据示例:

1、返回对象

定义返回对象的Web Method

 1:         [WebMethod]
 2:         public Employee GetEmployee()
 3:         {
 4:             return new Employee
 5:             {
 6:                 id = 1,
 7:                 name = "Shawn",
 8:                 age = 25
 9:             };
10:         }
11:  
.codearea { color: black; background-color: white; line-height: 18px; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,”BitStream Vera Sans Mono”,courier,monospace,serif; }.codearea pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap pre { white-space: pre-wrap; word-wrap: break-word; }.codearea pre.alt { background-color: rgb(247, 247, 255) ! important; }.codearea .lnum { color: rgb(79, 129, 189); line-height: 18px; }Flex前端代码:

 1:  <?xml version="1.0" encoding="utf-8"?>
 2:  <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 3:      <mx:Script>
 4:          <![CDATA[
 5:              import mx.rpc.events.FaultEvent;
 6:              import mx.rpc.events.ResultEvent;
 7:              import mx.controls.Alert;
 8:              private function onResult(event:ResultEvent):void
 9:              {
10:                  Alert.show(event.result.name);
11:              }
12:  
13:              private function onFault(event:FaultEvent):void
14:              {
15:                 Alert.show("调+event.message);
16:              }
17:  
18:              private function GetEmployee():void
19:              {
20:                  this.MyService.GetEmployee.send();
21:              }
22:          ]]>
23:      </mx:Script>
24:      <mx:Button label="Get Employee" click="GetEmployee()"/>
25:      
26:      <mx:WebService id="MyService" wsdl="http://localhost:4081/Flex.asmx?WSDL" useProxy="false" result="onResult(event)" fault="onFault(event)">
27:          <mx:operation name="GetEmployee"/>
28:      </mx:WebService>
29:  </mx:Application>
30:  

.codearea { color: black; background-color: white; line-height: 18px; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,”BitStream Vera Sans Mono”,courier,monospace,serif; }.codearea pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap pre { white-space: pre-wrap; word-wrap: break-word; }.codearea pre.alt { background-color: rgb(247, 247, 255) ! important; }.codearea .lnum { color: rgb(79, 129, 189); line-height: 18px; }运行结果:

image

2、返回DataTable

定义返回DataTable的Web Method:

 1:          [WebMethod]
 2:          public DataTable GetDataTable()
 3:          {
 4:              DataTable dt = new DataTable("Employees");
 5:              dt.Columns.Add("id", typeof(int));
 6:              dt.Columns.Add("name", typeof(string));
 7:              dt.Columns.Add("age", typeof(int));
 8:  
 9:              DataRow dr = dt.NewRow();
10:              dr["id"] = 1;
11:              dr["name"] = "Shawn";
12:              dr["age"] = 25;
13:              dt.Rows.Add(dr);
14:  
15:              dr = dt.NewRow();
16:              dr["id"] = 2;
17:              dr["name"] = "Jack";
18:              dr["age"] = 23;
19:              dt.Rows.Add(dr);
20:  
21:              return dt;
22:          }
23:  

.codearea { color: black; background-color: white; line-height: 18px; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,”BitStream Vera Sans Mono”,courier,monospace,serif; }.codearea pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap pre { white-space: pre-wrap; word-wrap: break-word; }.codearea pre.alt { background-color: rgb(247, 247, 255) ! important; }.codearea .lnum { color: rgb(79, 129, 189); line-height: 18px; }Flex前端代码:

 1:  <?xml version="1.0" encoding="utf-8"?>
 2:  <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 3:      <mx:Script>
 4:          <![CDATA[
 5:              import mx.rpc.events.FaultEvent;
 6:              import mx.rpc.events.ResultEvent;
 7:              import mx.controls.Alert;
 8:              private function onResult(event:ResultEvent):void
 9:              {
10:  
11:              }
12:  
13:              private function onFault(event:FaultEvent):void
14:              {
15:                 Alert.show("调+event.message);
16:              }
17:  
18:              private function GetDataTable():void
19:              {
20:                  this.MyService.GetDataTable.send();
21:              }
22:          ]]>
23:      </mx:Script>
24:      
25:      <mx:Panel width="400">
26:          <mx:DataGrid id="gvEmployee" dataProvider="{this.MyService.GetDataTable.lastResult.Tables.Employees.Rows}" width="100%">
27:              <mx:columns>
28:                  <mx:DataGridColumn headerText="ID" dataField="id"/>
29:                  <mx:DataGridColumn headerText="Name" dataField="name"/>
30:                  <mx:DataGridColumn headerText="Age" dataField="age"/>
31:              </mx:columns>
32:          </mx:DataGrid>
33:          <mx:ControlBar>
34:              <mx:Button label="Get DataTable" click="GetDataTable()"/>
35:          </mx:ControlBar>
36:      </mx:Panel>
37:      
38:      <mx:WebService id="MyService" wsdl="http://localhost:4081/Flex.asmx?WSDL" useProxy="false" result="onResult(event)" fault="onFault(event)">
39:          <mx:operation name="GetDataTable"/>
40:      </mx:WebService>
41:  </mx:Application>
42:  

.codearea { color: black; background-color: white; line-height: 18px; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,”BitStream Vera Sans Mono”,courier,monospace,serif; }.codearea pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap pre { white-space: pre-wrap; word-wrap: break-word; }.codearea pre.alt { background-color: rgb(247, 247, 255) ! important; }.codearea .lnum { color: rgb(79, 129, 189); line-height: 18px; }运行结果:

image

3、返回List<>

 1:          [WebMethod]
 2:          public List<Employee> GetEmployeeList()
 3:          {
 4:              return new List<Employee>
 5:              {
 6:                  new Employee
 7:                  {
 8:                      id = 1,
 9:                      name = "Shawn",
10:                      age = 25
11:                  },
12:                  new Employee
13:                  {
14:                      id = 2,
15:                      name = "Jack",
16:                      age = 23
17:                  }
18:              };
19:          }
20:  

.codearea { color: black; background-color: white; line-height: 18px; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,”BitStream Vera Sans Mono”,courier,monospace,serif; }.codearea pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap pre { white-space: pre-wrap; word-wrap: break-word; }.codearea pre.alt { background-color: rgb(247, 247, 255) ! important; }.codearea .lnum { color: rgb(79, 129, 189); line-height: 18px; }Flex前端:

 1:  <?xml version="1.0" encoding="utf-8"?>
 2:  <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 3:      <mx:Script>
 4:          <![CDATA[
 5:              import mx.collections.ArrayCollection;
 6:              import mx.rpc.events.FaultEvent;
 7:              import mx.rpc.events.ResultEvent;
 8:              import mx.controls.Alert;
 9:              private function onResult(event:ResultEvent):void
10:              {
11:                  var arr:ArrayCollection = this.MyService.GetEmployeeList.lastResult as ArrayCollection;
12:                  gvEmployee.dataProvider=arr;
13:              }
14:  
15:              private function onFault(event:FaultEvent):void
16:              {
17:                 Alert.show("调+event.message);
18:              }
19:  
20:              private function GetEmployeeList():void
21:              {
22:                  this.MyService.GetEmployeeList.send();
23:              }
24:          ]]>
25:      </mx:Script>
26:      
27:      <mx:Panel width="400">
28:          <mx:DataGrid id="gvEmployee" width="100%">
29:              <mx:columns>
30:                  <mx:DataGridColumn headerText="ID" dataField="id"/>
31:                  <mx:DataGridColumn headerText="Name" dataField="name"/>
32:                  <mx:DataGridColumn headerText="Age" dataField="age"/>
33:              </mx:columns>
34:          </mx:DataGrid>
35:          <mx:ControlBar>
36:              <mx:Button label="Get List" click="GetEmployeeList()"/>
37:          </mx:ControlBar>
38:      </mx:Panel>
39:      
40:      <mx:WebService id="MyService" wsdl="http://localhost:4081/Flex.asmx?WSDL" useProxy="false" result="onResult(event)" fault="onFault(event)">
41:          <mx:operation name="GetEmployeeList"/>
42:      </mx:WebService>
43:  </mx:Application>
44:  

.codearea { color: black; background-color: white; line-height: 18px; border: 1px solid rgb(79, 129, 189); margin: 0pt; width: auto ! important; overflow: auto; text-align: left; font-size: 12px; font-family: “Courier New”,”Consolas”,”Fixedsys”,”BitStream Vera Sans Mono”,courier,monospace,serif; }.codearea pre { color: black; line-height: 18px; padding: 0pt 0pt 0pt 12px ! important; margin: 0em; background-color: rgb(255, 255, 255) ! important; }.linewrap pre { white-space: pre-wrap; word-wrap: break-word; }.codearea pre.alt { background-color: rgb(247, 247, 255) ! important; }.codearea .lnum { color: rgb(79, 129, 189); line-height: 18px; }运行结果:

image

[转载]在Mono 2.8上部署ASP.NET MVC 2

mikel阅读(927)

[转载]在Mono 2.8上部署ASP.NET MVC 2 – 自由、创新、研究、探索 – 博客园.

Mono 2.8发布:C#4.0和更好的性能, 我们知道Mono 2.8对ASP.NET MVC 2的完全支持,下面我们就来测试下在Mono 2.8上部署ASP.NET MVC 2应用程序。我的环境是Opensuse 11.3,通过以下命令部署好Mono 2.8的开发环境,之所以说是开发环境是同时会更新MonoDevelop,支持Mono2.8的程序开发

zypper addrepo http://ftp.novell.com/pub/mono/download-stable/openSUSE_11.3 mono-stable
zypper refresh --repo mono-stable
zypper dist-upgrade --repo mono-stable

然后启动MonoDevelop生成一个ASP.NET MVC 2应用程序TestMvc2。

image

我们使用Apache2 + mod_mono进行部署,设置一个虚拟主机:

   1: <VirtualHost *:80>
   2:     ServerAdmin webmaster@dotnetting.com
   3:     ServerName www.dotnetting.com
   4:
   5:     # DocumentRoot: The directory out of which you will serve your
   6:     # documents. By default, all requests are taken from this directory, but
   7:     # symbolic links and aliases may be used to point to other locations.
   8:     DocumentRoot /srv/www/vhosts/dotnetting/public_html
   9:
  10:     # if not specified, the global error log is used
  11:     ErrorLog /srv/www/vhosts/dotnetting/logs/error.log
  12:     CustomLog /srv/www/vhosts/dotnetting/logs/access_log combined
  13:
  14:     # don't loose time with IP address lookups
  15:     HostnameLookups Off
  16:
  17:     # needed for named virtual hosts
  18:     UseCanonicalName Off
  19:
  20:     # configures the footer on server-generated documents
  21:     ServerSignature On
  22:
  23:
  24:     # Optionally, include *.conf files from /etc/apache2/conf.d/
  25:     #
  26:     # For example, to allow execution of PHP scripts:
  27:     #
  28:     Include /etc/apache2/conf.d/mod_mono.conf
  29:
  30:     MonoServerPath www.dotnetting.com "/usr/bin/mod-mono-server4"
  31:     MonoDebug www.dotnetting.com true
  32:     MonoSetEnv www.dotnetting.com MONO_IOMAP=all
  33:     MonoApplications www.dotnetting.com "/:/srv/www/vhosts/dotnetting/public_html"
  34:     <Location "/">
  35:       Allow from all
  36:       Order allow,deny
  37:       MonoSetServerAlias www.dotnetting.com
  38:       SetHandler mono
  39:       SetOutputFilter DEFLATE
  40:       SetEnvIfNoCase Request_URI "\.(?:gif|jpg?g|png)$" no-gzip dont-vary
  41:     </Location>
  42:     <IfModule mod_deflate.c>
  43:       AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
  44:     </IfModule>
  45:
  46: </VirtualHost>

这是一个通用的ASP.NET虚拟主机配置,唯一的一行不同就是MonoServerPath上设置的Mvc1还是mvc2,我们这里设置为 mod-mono-server4,如果你没有修改这个地方,会收到一个错误是web.config 的 targetFramework不对。然后把我们生成测试程序拷贝到/srv/www/vhosts/dotnetting/public_html 。

注:Mono2.8已经移除了对.NET 1.1的支持,因此也就不能设置为mod-mono-server1

重启Apache2

service apache2 restart

通过浏览器访问www.dotnetting.com ,记得在访问之前在host文件中配置域名的解析。可以看到下面的页面:

image

附:个人常用的VIM命令列表

作者: 自由、创新、研究、探索……
出处:http://shanyou.cnblogs.com/
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
分享到QQ空间
腾讯微博:http://t.qq.com/geffzhang

[转载]ASP.NET MVC 3 Beta新特性以及.Net开源的趋势

mikel阅读(972)

[转载]ASP.NET MVC 3 Beta新特性以及.Net开源的趋势—-最新译文 – JasenKin – 博客园.

NuPack – .NET的开源软件包管理器

NuPack是一个开源的软件包管理器,它使你在项目中能够更加容易的查找、安装和使用.NET 库。它能够和所有的.NET 项目类型很好的一起工作(包括,没有任何限制的,ASP.NET Web Forms和ASP.NET MVC).

NuPack 使维护开源项目的开发者(例如, Moq, NHibernate, Ninject, StructureMap, NUnit, Windsor, RhinoMocks, Elmah, 等等) 能够去打包他们的库,并且使用一个在线的,可查找的gallery/catalog 来注册它们。客户端NuPack tools –它与Visual Studio 集成度很高– 让任何一名 .NET开发者在他们的项目中能够轻松的使用这些类库,并且安装它们。

NuPack 处理库之间的依赖管理(例如: library1 依赖于library2). 它同样使你在后续的项目中能够很容易的修改(并且随意的移除) 库. 它支持更新web.config 文件(如果一个包需要配置设置). 同样,它允许程序包来增加PowerShell scripts 到一个项目中 (例如: scaffold commands).最重要的, NuPack 是透明的– 并且在系统层上没有安装任何东西. 相反,它致力于更加容易的让你使用你的项目来管理你的库。

NuPack本身就是一种开源的项目.  The Outercurve Foundation (formerly CodePlex Foundation)今天宣布接纳NuPack 项目到the ASP.NET Open Source Gallery中。

我们的目标是使NuPack在.NET项目中尽可能简单地整合开源库。它将支持Visual Studio的所有版本。今天,你能够使用它的第一个开发版本来开始。

一个简单的NuPack场景– 使用 ELMAH

作为一个简单的例子来显示了NuPack能够做什么—–让我们假设我们正在进行一 项全新的 ASP.NET 应用程序开发,并且想要使用的流行的“ELMAH”库来记录和报告我们网站的错误。ELMAH安装,你需要手动下载,解压它,增加引用到你的项目中,确保 你拥有源码控制绑定来正确的安装库,并更新你的应用程序的web.config 文件,包括ELMAH HttpModule记录。所有都是可行的——但有点乏味。

当NuPack安装之后,你能简单地打开新的“Package Manager Console”,在里面键入”Add-Package elmah”。

image

键入”Add-Package elmah” ,导致NuPack 核查Elmah库的在线定位, 下载它, 增加它的引用到你的项目中, 并且自动的增加适当的Elmah 注册条目在你的应用程序的web.config文件中:

image

现在我们已经为我们的项目设置、安装了Elmah,并且启用了错误报告记录。不需要额外的手工步骤来使它工作。

学习和了解更多关于NuPack的知识

点击下面的链接来学习和了解更多关于NuPack的内容和大量的情景:

.NET 和开源

我们认为NuPack将是一个 .NET stack 前进的基本成分。这将鼓励更多的开发者使用开源库。有一个标准的软件包管理器集成到Visual Studio ,将同样很有希望的鼓励更多的开源.NET项目创建。

ASP.NET MVC 3 Beta

这个版本是 ASP.NET MVC 3 Preview的一个重要的更新,它包含了大量的功能改善。

除了ASP.NET MVC 3的特性(introduced with the first preview),今天的Beta版本包括:

  • Razor 增强功能: ASP.NET MVC 3 支持这个新的Razor 视图引擎选项。除了ASP.NET MVC 3 Preview中 的功能外,今天的Beta版本增加大量的额外功能: Cleaner MVC integration – 包括使用一个新的@model 语法来清洁指定类型被传送到视图 。一个新的@helper 语法来申明可重用的HTML helpers 。一个新的 @* *@ 注释语法。 支持使用Razor的C#和VB 风格。

  • 新的 View Helpers: 新的view helper方法现在已经支持.  它包括一个新的Chart() helper method来动态创建charts (和<asp:chart> control in ASP.NET 4 一样的特征– 而现在使用view 帮助方法)。同样,一个新的WebGrid() 帮助方法能够被用来创建data-grid 风格的用户界面(包括分页和排序).
  • 兼容 JavaScript 和HTML 5: 现在,在 ASP.NET MVC 中,AJAX 和Validation helpers 同时使用unobtrusive JavaScript 默认的方法。 Unobtrusive JavaScript 避免注入内联的JavaScript至HTML中,并且使用新的HTML 5 数据约定来使行为分离(它同样在旧的浏览器中很方便)。 这将使你的HTML更小,更清洁,同样使它更加容易的交换和定制JS 库。在ASP.NET MVC 3中Validation helpers现在同样支持使用JQueryValidate这个默认的插件。

  • 依赖性注射模式: 最初的ASP.NET MVC 3 Preview 在Controllers, Views 和Action Filters中更好的支持依赖注入(DI) 。 今天的Beta 版本扩展了该功能,以更好的依赖性注入模式支持Model Binders, Model Validation Providers, Model Metadata Providers, 和Value Providers。它同样支持一个新的IDependencyResolver 接口,这个接口更加容易的集成依赖注入框架。
  • NuPack 集成: ASP.NET MVC 3 自动的安装NuPack 。它将利用NuPack来发现和增加大量的MVC 开展和库到你的项目中。

  • 其他的: 最初的ASP.NET MVC 3 Preview 增加很多额外的helpers 和类 来更好的日常编码。  这个 beta包括大量额外的改进:更多的颗粒XSS HTML 输入验证,HTML helper 改进以支持HTML 5,Crypto helpers 和散列密码,更加简单的Email APIs, 改进的“New Project” 对话框,等等。

学习和了解更多关于ASP.NET MVC 3的内容

点击下面的链接来了解更多的关于ASP.NET MVC 3 Beta:

下载

Click here 使用Microsoft Web Platform Installer下载和安装ASP.NET MVC 3 Beta 。

或者你也可以下载并安装 ASP.NET MVC 3 Beta(使用一个单独的安装文件) here (注:对于今天的beta 版本,你需要先安装AspNetWebPages.msi,然后是AspNetMVC3Setup.exe文件).

WebMatrix Beta 2

这个版本是WebMatrix Beta 1 的改进版本,它包括了大量的特征改进。

除了WebMatrix 特性 introduced with the first beta,今天的Beta 2 版本还包含:

  • Web Page 增强功能: WebMatrix 通过使用一种新的Razor语法来支持创建单独的ASP.NET Web 页面。它包含同样的语法改进(@helper, @* comment *@, etc) 。现在它同样支持使用VB 和C#创建页面。

  • 改进的模板: WebMatrix 包含了针对于常见场景的模板项目 。这些模板项目现在使用HTML 5 和 CSS 3 (并且同样与downlevel browsers一同工作)。一个新的Wishlist 项目模板在Beta 2中增加了。

  • NuPack集成: WebMatrix 提供NuPack集成并且支持一个基于网页的管理来安装库到你正在致力于的项目中。

  • Toolkit 支持: 我们正在发布一个Toolkit,它提供方便的能够在ASP.NET 应用程序中使用的helpers 。它包含针对于Analytics, Facebook, GamerCard, Gravatar, LinkShare, Captcha, Twitter 和Video scenarios的helpers。

下载

Click here 下载和安装WebMatrix Beta 2。

总结

今天的发布进一步进化和提升 Microsoft Web Stack。以上所有的功能与.NET 4 and VS 2010整合在一起工作,而不修改现有任何文件(它们都是附加并且安全的在你的机器上安装)。

原文地址:http://weblogs.asp.net/scottgu/archive/2010/10/06/announcing-nupack-asp-net-mvc-3-beta-and-webmatrix-beta-2.aspx

[转载]安装 SQL SERVER MsiGetProductInfo 无法检索 Product Code 解决方案

mikel阅读(864)

[转载]安装 SQL SERVER MsiGetProductInfo 无法检索 Product Code 解决方案 – SQL Server教程 – CND8学院.

昨天升级服务器上的SQL SERVER上遇到了以下问题MsiGetProductInfo” 无法检索 Product Code {F1F1E8540-CF57-485B-9994-BE9E02D29193}的包的 ProductVersion;刚开始就觉得很郁闷,我明明清理了注册了嘛,难道还有值没清除的,查了下资料--果然是!在 HKEY_Classes_Root\installer\UpgradeCodes有相应的值没删除!那么我们怎么查找相应的值呢(这点上很多人说得不 明不白的),在这里我清晰的描述一下:

当系统提示如 {F1F1E8540-CF57-485B-9994-BE9E02D29193}这个GUID时,

首先把这个GUID的前段“F1F1E8540” 倒排 成为 0458E1F1F ,然后HKEY_Classes_Root\installer\UpgradeCodes里查找这个倒排的值,

查找到后,删除对应的父节点;

到此,这个环节上的安装问题就应解决,不过有时系统可能会提示多个Guid,不过你不要担心,接着按上述方法处理。

[转载]使用NVelocity快速实现Flexigrid

mikel阅读(1296)

[转载]使用NVelocity快速实现Flexigrid – Ariel Lu – 博客园.

自从去年偶然间发现Flexigrid这款JQuery的表格控件,就被它深深地吸引住了,华丽的外表、强大的功能、灵活的扩展性,最关键的是它不臃肿。如果追求功能强大,倒不如去使用ExtJs了。前段时间园友华磊给出了Flexigrid的ASP.NET解决方案,但我觉得封装成用户控件丧失了灵活性,而且它不再是一个客户端控件,不能按照我们的想法去随心所欲地操纵它。

既 然我们想保持它在前端的灵活性,只有另辟蹊径,从其它方面着手去简化工作。每次使用它,在后台获取数据,转成JSON格式也是一个比较繁琐的工作,有没有 一种方案能简化这些步骤,每次只需通过简单的配置和一两条SQL语句就能达到我们想要的效果呢?答案当然是肯定的。于是我想到了用模板引擎 NVelcity来实现这个方案。只要能把Flexigrid异步请求的参数能在SQL语句中使用,就可以解决这个问题了。

于是我们需要一个通用的WebService方法来接受、处理Flexigrid的参数:首先处理Flexigrid本身在获取数据的时候用的六个参数,代码如下:

//处理FlexiGrid的参数
//$page  第几页
//$rp  每页的条数
//$sortname  排序字段
//$sortorder  排序方向
string[] flexiGridParameters = { "page", "rp", "sortname", "sortorder", 
                                   "query", "qtype" };
Dictionary<string, object> parameters = new Dictionary<string, object>();
foreach (string flexiGridParameter in flexiGridParameters)
{
    string valueOfFlexiGridParameter = Context.Request.Params[flexiGridParameter];
    if (!string.IsNullOrEmpty(valueOfFlexiGridParameter))
    {
        parameters.Add(flexiGridParameter, valueOfFlexiGridParameter);
    }
}

有时候除了默认的这几个参数,我们还需要一些自定义的参数,为了方便处理,自定义参数需以”param_”开头:

//加入自定义参数,以 "param_" 开头
foreach (string userDefinedParameterName in Context.Request.Params.AllKeys
    .Where(o => o.StartsWith("param_")))
{
    parameters.Add(userDefinedParameterName,
        Context.Request.Params[userDefinedParameterName]);
}

另外page和rp为别表示页数和每页的条数,而我们需要的是起始条数和结束条数:

//将page和rp两个参数转成整数,再加入下面两个参数,方便写sql语句
//$startIndex  开始的行号
//$endIndex  结束的行号
int page = 1;
if (parameters.ContainsKey("page") && parameters.ContainsKey("rp"))
{
    page = Convert.ToInt32(parameters["page"]);
    int rp = Convert.ToInt32(parameters["rp"]);
    parameters["page"] = page;
    parameters["rp"] = rp;
    parameters.Add("startIndex", (page - 1) * rp + 1);
    parameters.Add("endIndex", page * rp);
}

好了,需要的参数都有了,剩下的工作就是如果写出一条用上上述参数的SQL语句并且动态地去解析它,在这里我选择了模板引擎NVelcity(本文中使用的是Castle的1.1版,这里有详细介绍)。现在我们要使用模板语言返回一个我们需要的数据结构,模板中定义如下:

#*
* 已有参数说明
$page  第几页
$rp  每页的条数
$sortname  排序字段
$sortorder  排序方向
$startIndex  开始的行号
$endIndex  结束的行号
$param_xxxx  自定义参数,xxxx为任意字符串

* 需要返回的数据结构说明
$result.rowsSql  获取数据的sql语句(必须有)
$result.totalSql  分页时取数据总数的sql语句(分页时必须有)
$result.id  FlexiGrid中的行id所对应的字段名(需要行id时指定,不指定时行id为空)
*#

这个时候又出现新的问题了,很多情况下SQL语句是一段很长的文本,而模板语言不支持换行,写在一行中可阅读性很差,显然是不符合要求的。这个时候就需要扩展一个模板语言中解析字符串的函数,把SQL语句写在另一个文本文件中,在模板中使用这个方法就可以啦。

static object ReadFileContent(object[] parameters)
{
    if (parameters.Length < 1)
    {
        return string.Empty;
    }
    DirectoryInfo info = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory
        + NVelocityConstants.TEMPLATE_DIRECTORY);
    FileInfo[] files = info.GetFiles(parameters[0].ToString(),
        SearchOption.AllDirectories);
    if (files.Length > 0)
    {
        string content = File.ReadAllText(files[0].FullName);
        List<string> argList = new List<string>();
        if (!string.IsNullOrEmpty(content))
        {
            for (int i = 1; i < parameters.Length; i++)
            {
                argList.Add(parameters[i] != null ?
                    parameters[i].ToString() : string.Empty);
            }
        }
        if (argList.Count > 0)
        {
            string[] ps = argList.ToArray();
            content = string.Format(content, ps);
        }
        return content;
    }
    return string.Empty;
}

回到刚才的WebService方法中,使用NVelocity解析刚才的模板:

//解析模板,取回FlexiGrid所需的sql语句,result类型为KeyValueObject
//$result.rowsSql  获取数据的sql语句(必须有)
//$result.totalSql  分页时取数据总数的sql语句(分页时必须有)
//$result.id  FlexiGrid中的行id所对应的字段名(需要行id时指定,不指定时行id为空)
NVelocityHelper velocity = new NVelocityHelper();
//注入工具类和参数
velocity.Add("helper", new HelperDuck());
foreach (string parameterName in parameters.Keys)
    velocity.Add(parameterName, parameters[parameterName]);
//得到模板执行结果
object result = velocity.GetResultFromVm(templateFileName);
if (result is KeyValueObject)
{
    KeyValueObject keyValueResult = (KeyValueObject)result;
    string rowsSql = string.Format("{0}", keyValueResult.GetInvoke("rowsSql"));
    string totalSql = string.Format("{0}", keyValueResult.GetInvoke("totalSql"));
    string id = string.Format("{0}", keyValueResult.GetInvoke("id"));

现在SQL语句已经有了,执行它,并序列化成JSON结构:

DataTable dt = Utils.ExecuteTable(rowsSql);
List<FlexiGridRow> rows = new List<FlexiGridRow>();
foreach (DataRow dr in dt.Rows)
{
    rows.Add(new FlexiGridRow()
    {
        id = dt.Columns.Contains(id) ? string.Format("{0}", dr[id]) : string.Empty,
        cell = Utils.DbObjectArrToCsStringArr(dr.ItemArray)
    });
}
int total = -1;
if (!string.IsNullOrEmpty(totalSql))
    total = Convert.ToInt32(Utils.ExecuteTable(totalSql).Rows[0][0]);

object flexiGridResult = new
{
    page = page,
    total = total > -1 ? total : rows.Count,
    rows = rows
};
Context.Response.Write(new JavaScriptSerializer().Serialize(flexiGridResult));

至此准备工作就全部完成了,下面我们通过一个示例来看一下效果如何:

1.首先新建一个文本文件用来存放SQL语句:

SELECT CompanyName, ContactName, ContactTitle, Address, City, Phone FROM (
    SELECT 
    ROW_NUMBER() OVER (ORDER BY {0} {1}) ROW,
    CompanyName, ContactName, ContactTitle, Address, City, Phone
    FROM Customers
) A where Row between {2} and {3}

2.添加一个NVelocity模板,用来获取我们想要的SQL语句

#set($result = $helper.createkeyvalueobject())
#set($result.rowsSql = $helper.readfilecontent("FlexiGrid_获取数据.sql", 
$sortname, $sortorder, $startIndex, $endIndex))
#set($result.totalSql = "SELECT COUNT(*) FROM Customers")
#set($result.id = "CompanyName")

3.前端调用

jQuery(document).ready(function () {
    var maiheight = document.documentElement.clientHeight;
    var w = jQuery("#ptable").width() - 3;
    var otherpm = 150; //GridHead,toolbar,footer,gridmargin
    var gh = maiheight - otherpm;

    var option = {
        height: gh, //flexigrid插件的高度,单位为px
        width: w,
        url: "WebService/CommonWebService.asmx/GetFlexiGridDataByTemplate",
        colModel: [
            { display: "公司名称", name: "CompanyName", width: 200, sortable: true },
            { display: "联系人名称", name: "ContactName", width: 120, sortable: true },
            { display: "标题", name: "ContactTitle", width: 150, sortable: false },
            { display: "地址", name: "Address", width: 250, sortable: true, hide: true },
            { display: "城市", name: "City", width: 100, sortable: true },
            { display: "电话", name: "Phone", width: 100, sortable: true }
        ],
        params: [
            { name: "templateFileName", value: "FlexiGrid_获取数据.htm" }
        ],
        buttons: [
              { name: "Add", displayname: "新增", onpress: toolbarItem_onclick },
              { name: "Delete", displayname: "删除", onpress: toolbarItem_onclick }
        ],
        sortname: "CompanyName",
        sortorder: "asc",
        title: "联系人列表",
        usepager: true,
        useRp: false,
        //rp: 5,
        rowbinddata: true,
        showcheckbox: true,
        rowhandler: rowEditHandler,
        selectedonclick: false,
        singleselected: true,
        //gridClass: "flexigrid"
        gridClass: "bbit-grid"
    };
    var grid = jQuery("#curtomerGrid").flexigrid(option);
});

怎么样,是不是很简单。最后让我们看看效果如何?

image

注:本文使用的Flexigrid为园友假正经哥哥修改过的版本,数据库使用的Northwind。

全部代码

[转载]javascript 实现单击和双击并存

mikel阅读(950)

[转载]javascript 实现单击和双击并存 – 功夫 熊猫 – 博客园.

在我们进行网页开发的过程中经常会遇到这么一个问题,为一个链接注册双击事件,或者让一个按钮或者其他元素上面同时注册单击或者双击事件,这时候我 们发现网页中的双击事件似乎永远都不会起作用,原因是当我们点击一次的时候,就被超链接或者单击事件截获了,本文描述了一个如何解决这个技术问题的具体方 法。本解决方案的实现原理是,单击事件和双击事件都调用同一个方法,我们根据两次鼠标点击的间隔事件来判断到底是单击还是双击事件。单击事件来临的时候先 不调用,等一小段时间,过了这段时间,如果没有下一次单击来临就开始调用单击对应的操作,如果有下一次点击就调用双击。
详细描述请参加下面代码清单:
< HTML>
< HEAD>
< TITLE> JavaScript 实现单击和双击并存 < /TITLE>
< META NAME=” Generator” CONTENT=” EditPlus” >
< META NAME=” Author” CONTENT=” http://www.javabiz.cn/” >
< META NAME=” Keywords” CONTENT=” ” >
< META NAME=” Description” CONTENT=” ” >
< /HEAD>

< BODY>
< SCRIPT LANGUAGE=” JavaScript” >
< !–
var dcTime=250;       // doubleclick time
var dcDelay=100;     // no clicks after doubleclick
var dcAt=0;               // time of doubleclick
var savEvent=null; // save Event for handling doClick().
var savEvtTime=0;   // save time of click event.
var savTO=null;       // handle of click setTimeOut

function showMe(txt) {
document.forms[0].elements[0].value += txt;
}

function handleWisely(which) {
switch (which) {
case ” click” :
savEvent = which;
d = new Date();
savEvtTime = d.getTime();
savTO = setTimeout(” doClick(savEvent)” , dcTime);
break;
case ” dblclick” :
doDoubleClick(which);
break;
default:
}
}

function doClick(which) {
if (savEvtTime – dcAt < = 0) {
return false;
}
showMe(” 单击” );
}

function doDoubleClick(which) {
var d = new Date();
dcAt = d.getTime();
if (savTO != null) {
savTO = null;
}
showMe(” 双击” );
}

//–>
< /SCRIPT>

< p>
< a href=” JavaScript:void(0)”
onclick=” handleWisely(event.type)”
ondblclick=” handleWisely(event.type)”
style=” color: blue; font-family: arial; cursor: hand” >
点击一下看看结果:
< /a>
< /p>

< form>
< table>
< tr>
< td valign=” top” >
事件模式: < textarea rows=” 4″ cols=” 60″ wrap=” soft” > < /textarea>
< /td>
< /tr>
< tr>

< td valign=” top” >
< input type=” Reset” >
< /td>
< /tr>
< /table>
< /form>
< /BODY>
< /HTML>