[转载]网站性能指南(一)概述

mikel阅读(1255)

[转载]【网站性能指南】(一)概述 – 技术弟弟 – 博客园.

【概观】

  • 什么使我们的网站变慢?
  • Http 协议
  • 通过更好的性能省钱和赚钱
  • 性能规则

【什么使网站变慢】

  • 对于大多数现代的网站,仅仅有10%-20%的响应时间是用于生成和加载html document的。

那么,其他的时间用于加载什么呢?确切的说,如下:

  1. css
  2. JavaScriptJQuery,plugin 等等)
  3. images

让我们使用一个工具去看看-Fiddler (http://www.fiddler2.com/fiddler2/)

首先打开fiddler,然后使用浏览器访问 www.microsoft.com

这时候我们可以看到fiddler监控到客户端与微软网站服务器之间的交互情况如下图:

 

注意fiddler 右边的选项卡,有一个timeline。载入default.asp话费了大概1s的时间。让我们全选这些行。再去看看timeline,如下图

 

这时候我们根据数据就可以证明前边的观点,对于某个网站来说,80%的时间是用于加载css/JS/image的。

 

【Http 协议】

对于http协议的理解是非常重要的,因为它定义了web 浏览器和 web 服务器如何交互。

  • Hypertext Transfer Protocol

对于这点来说,最重要的是text,它不是基于二进制的协议,而是基于text的。

  • 协议是1997年1月在 RFC(Http1.1)定义的。
  • 请求/相应 模式。客户端浏览器发送特定的request,服务器返回response
  • Header 和body。 每个request/response 有header和body

以下是 http协议的内容。我十分推荐你们阅读它:http://tinyurl.com/8395lq

 

HttpRequest

我们使用fiddler观察一下我们访问微软的httprequest。

选中第一个记录。右边选项卡依次->Inspecotrs->Raw

我们简单分析,

Get指明了url和http的版本。

host指明了host的地址。

accept-language指明了浏览器使用的语言

accept-Encoding指明了是否可以使用对浏览器到服务器之间的数据进行压缩。

 

HttpResponse

下面我们来看看刚才我们请求的响应。

我在fiddler中选中的是第12行数据,选中右边选项卡->Inspecotrs->Raw

# Result Protocol Host URL Body Caching Content-Type Process Comments Custom
12 200 HTTP www.microsoft.com /en-us/homepage/shared/core/2/js/js.ashx?& 3 private text/JavaScript; charset=utf-8 chrome:3856

 

Http/1/1 200 OK。是告诉大家,一切运行良好。 200是一种状态,如果遇到问题可能会是404,500等。
其他细节,大家可以自己查一下资料。

【通过更好的性能省钱和赚钱】

大家都可以明白。提升网站的性能,可以让用户更加满意。而这也能让我们省钱和赚钱。

  • 省钱的办法:

使用更小的带宽

更少的服务器数量

  • 赚钱的办法:

增长的销售和流量

    • -每增加100毫秒载入Amzon.com 会减少销售额的1%.web
    • -当google maps 的主页大小从100KB减少到70-80k时,流量在第一周会增在10%,在随后的3周会增长到25%。
    • -google 已经根据你网站的性能去帮助决定搜索排名。

对于网站性能对流量和销售产生的影响请参见相关文章《web性能心理学》http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/

 

【性能规则】

  1. 减少http request

如何减少http request呢?我们根据上边提到fiddler侦听到的http request 得知,好多次请求是去获取css,JavaScript,和image的。

首先我们先来看看一个网站:

它是一个普通的网站他可以使用JQuery来弹出图片,我们用fiddler 来试试它。

我们可以看出。他包含了一些css文件,也使用了JQuery

让我们看看这个网站的另一个版本。

样子是一模一样的,我就不show图了。

让我们看看fiddler 又帮我们抓到了什么:

js和css文件都变成1个了。我们把上边的js文件合并成1个js文件。这样我们就减少了httprequest的次数。

2.发送尽可能少的数据

我们回到fiddler。查看第一个网站的jQuery文件“jQuery-1.6.2.js。

它的普通版本是236k。

第一个网站需要加载js的总大小是279k。

而第二个网站需要加载js的大小是50.8k。

我们做了什么呢?只是把js文件里的白空格去掉了,就是对js文件的压缩。

css文件也如此。在最后的product版本上,我们使用合并的文件可以减少httprequest次数。当然在Debug的时候我们要保留空行增加代码的可读性。

关于压缩js的工具我们在网上可以找到很多,就不列举。

3.减少交互的次数(适当使用缓存)

让我们刷新一下第二个网站,并观看fiddler。我们可以发现,第二次加载至向服务器获取了default.aspx。

并没有重新加载js、css和图片。因为浏览器已经替我们缓存了那些文件。

 

后续的章节是

【性能测量】

【基础实施性能】

【前段性能】

【五花八门的性能】

敬请关注

[转载]网站性能指南(二)网站性能测量神器

mikel阅读(1469)

[转载]【网站性能指南】(二)网站性能测量神器 – 技术弟弟 – 博客园.

上一章我讲了很多关于Fiddler的东西。其实有很多检测工具可以使用,如 Fiddler 、chrome、firebug、Network Monitor、IIS 和一些第三方的service。

首先我们还是先继续回顾一下fiddler的功能

【Fiddler】

  •  追踪工具,尤其针对Http
  •  展示完成的request和response
  •  可以保存session存档
    • 在提高我网站性能之前,我先把网站相关信息保存起来。等我优化之后,我可以拿出来做对比。哦,原来我的站点性能提高了这么多!

  •  网页加载耗时时间轴
  •  统计。还是以微软的网站为例:
  • 我们可以很清楚的看到加载了哪些类型的文件,已经文件的大小。

 

 

【Chrome 浏览器】


Chrome 是google 开发的一个非常适合开发人员使用的浏览器。它同样可以测量一个网站的性能,

 现在一个chrome浏览器,并且按F12。你可以看到很多开发人员选项。我们可以看到以下工具:

让我们试试他们都能干吗,功能可能一带而过,因为我们这节只关注性能相关的功能。

element :可以让我们观察当前页面包含哪些html元素。

Resources:引用哪些资源。

network 和timeline:功能类似fiddler。是关于http request 、response和timeline情况

 

profiles:可以收集三种profile。比如JavaScript 占用多少cpu。大家不防自己试试。

 

 

Audits 就更酷了。它可以为你的站点提出优化建议。就像下图。他提供了一些建议。开启gzip压缩,使用浏览器缓存移除没有使用到的css引用等。这个页面就是我写博客时候用的。所以,咱们的院子还可以提高性能:)

【Firebug】

 由于篇幅有限,我这里就不详细介绍了,功能上和chrome差不多。下载一个firefox浏览器之后,安装firebug插件就可以使用了。呼出也是F12(让我想起了小时候的传奇外挂。。)

 配上个图:

 

【Microsoft Network Monitor】

  •  通用的网络追踪工具,适用于多种协议。http、tcp/IP等等。
  •  网络适配器的钩子。
  • 在多个等级去看网络的结构。
  •  对于特定的协议、ip地址等应用不同过滤器。

以下是获得这个免费工具的地址:http://www.microsoft.com/en-us/download/details.aspx?id=4865

看到这的朋友们就下载下来试试吧。

首先创建一个新的Capture-》工具栏里的”New Capture“。然后点击上边绿色三角 start。切换到IE浏览器。访问www.microsoft.com。然后切换回来点击stop。

我们可以发现有很多信息。包含了很多协议。现在我们添加一个过滤器:http。

第一条信息居然是搜狐mail。不要紧,一定是它定期去发送http request获取mail信息了。

我们可以看到location实际访问的***/mail/check。是的,我们想对了。它就是去检查邮件啦。

我在这里只是想抛砖引玉。如果你对Microsoft Network Monitor感兴趣。请参见:http://en.wikipedia.org/wiki/Microsoft_Network_Monitor

 

【IIS 日志文件】

IIS对于性能测量方面能为我们提供2个feature:

  •  所用时间
  •  日志剖析
    • 通用方法查询IIS日志文件、事件日志等
    • 查询语法特别接近SQL语句
    • 记录站点健康信息

所用时间

我们可以通过IIS的日志文件进行我们的性能分析。首先打开IIS->选定站点->logging(日志)

 

点击选择字段。并且勾选上所用时间以及你感兴趣的字段。

点击确定之后,每当有request来到你的IIS服务器。IIS都会为你记录一份详尽的日志。

日志剖析

LogParser 是一个命令行工具,可以通过SQL 语句对日志进行分析统计。可以分析IIS日志,还可以分析系统事件日志,CSV,XML等格式日志

基本的用法如下:

LogParser –i:输入文件的格式 –o:输出格式 “SQL语句”
例如下面的例子是用Log Parser统计访问整个IIS站点次数最多的IP:
logparser.exe -i:IISW3C SELECT TOP 25   cs-uri-stem as Url,   COUNT(*) As Hits  FROM c:\inetpub\logs\LogFiles\W3SVC1\*  GROUP BY cs-uri-stem  ORDER By Hits DESC

如果你对logparser 感兴趣。可以再去读读 这篇文章:http://blogs.msdn.com/b/carlosag/archive/2010/03/25/analyze-your-iis-log-files-favorite-log-parser-queries.aspx

【第三方服务】

Keynote http://www.keynote.com/ ,Gomez(收费的)

  • 提供性能分析服务。
  • 允许我们比较自己和其他站点性能上的差异
  • 提供代理服务
  • 响应时间和每X分钟的有效性。

 

好,感谢大家的阅读。下一章我们会介绍【基础设施性能】。

[转载]ASP.NET开发工具整理第一季

mikel阅读(1170)

[转载]ASP.NET开发工具整理第一季 – rickc2k – 博客园.

1.Microsoft SQL Server Compact:
http://www.microsoft.com/en-us/download/details.aspx?id=17876
简化的本地数据库,标准连接字符串为”Data Source=MyData.sdf;Persist Security Info=False;”。

2.JQuery.template()函数
在新版本JQuery中的模板函数,快速提高重复代码或DOM的生成。

复制代码
// Convert the markup string into a named template
$.template( "summaryTemplate", "<li>${Name}</li>" ); function renderList() { // Render the movies data using the named template: "summaryTemplate"
    $.tmpl( "summaryTemplate", movies ).appendTo( "#moviesList" ); }
复制代码

3.jqPlot客户端图表脚本库
http://www.jqplot.com/images/leftcharts.jpg

4.JQuery.simulate
模拟键盘鼠标事件的测试脚本库
https://github.com/eduardolundgren/jquery-simulate

5.QUnit
客户端JavaScript脚本测试框架
http://docs.jquery.com/Qunit

6.modernizr
浏览器版本及支持功能测试
http://modernizr.com/

7.Backbone.js
提供客户端脚本的model键值绑定及自定义事件功能
http://backbonejs.org/

8.Knockout.js
实现客户端脚本的MVVM模式
http://knockoutjs.com/

9.SproutCore
一个高效的Web框架
http://sproutcore.com/

10.BBQ plugin
在HTML5中实现浏览历史及导航功能
http://benalman.com/projects/jquery-bbq-plugin/

[转载]Download jQuery EasyUI 1.3 - jQuery EasyUI

mikel阅读(1371)

[转载]Download jQuery EasyUI 1.3 – jQuery EasyUI.

Download JQuery EasyUI 1.3

Current Version: 1.3

ChangeLog

Bug
  • combogrid: When set to ‘remote’ query mode, the ‘queryParams’ parameters can’t be sent to server. fixed.
  • combotree: The tree nodes on drop-down panel can not be unchecked while calling ‘clear’ method. fixed.
  • datetimebox: Setting ‘showSeconds’ property to false cannot hide seconds info. fixed.
  • datagrid: Calling ‘mergeCells’ method can’t auto resize the merged cell while header is hidden. fixed.
  • dialog: Set cache to false and load data via ajax, the content cannot be refreshed. fixed.
Improvement
  • The HTML5 ‘data-options’ attribute is available for components to declare all custom options, including properties and events.
  • More detailed documentation is available.
  • panel: Prevent script on panel body from running twice.
  • accordion: Add ‘getPanelIndex’ method.
  • accordion: The tools can be added on panel header.
  • datetimebox: Add ‘timeSeparator’ option that allows users to define the time separator.
  • pagination: Add ‘refresh’ and ‘select’ methods.
  • datagrid: Auto resize the column width to fit the contents when the column width is not defined.
  • datagrid: Double click on the right border of columns to auto resize the columns to the contents in the columns.
  • datagrid: Add ‘autoSizeColumn’ method that allows users to adjust the column width to fit the contents.
  • datagrid: Add ‘getChecked’ method to get all rows where the checkbox has been checked.
  • datagrid: Add ‘selectOnCheck’ and ‘checkOnSelect’ properties and some checking methods to enhance the row selections.
  • datagrid: Add ‘pagePosition’ property to allow users to display pager bar at either top,bottom or both places of the grid.
  • datagrid: The buffer view and virtual scroll view are supported to display large amounts of records without pagination.
  • tabs: Add ‘disableTab’ and ‘enableTab’ methods to allow users to disable or enable a tab panel.

License: GPL License Commercial License

Plugins

draggable
droppable
resizable
panel
tabs
accordion
layout
linkbutton
menubutton
splitbutton
menu
form
combo
combobox
combotree
combogrid
numberbox
validatebox
searchbox
messager
progressbar
spinner
numberspinner
timespinner
window
dialog
datagrid
propertygrid
pagination
tree
treegrid
calendar
datebox
datetimebox
slider
parser

Download this EasyUI package:

[转载]关于SQL删除语句TRUNCATE和DELETE

mikel阅读(905)

[转载]关于SQL删除语句TRUNCATE和DELETE – dessay – 博客园.

truncate操作同没有where条件的delete操作十分相似。
1、无论truncate大表还是小表速度都非常快。delete要产生回滚信息来满足回滚需求,而truncate是不产生的。
2、truncate是DDL语句进行隐式提交,不能进行回滚操作。
3、truncate重新设定表和索引的HWM(高水标记),由于全表扫描和索引快速扫描都要读取所有的数据块知道HWM为止。所以全表扫描的性能不会因为delete而提高,但是经过truncate操作后速度会很快。
4、truncate不触发任何delete触发器
5、不能赋给某个用户truncate其它用户表的权限。如果需要trucate其它用户表的权限必须对该用户赋DROP ANY TABLE权限。
6、当表被truncate后,这个表和索引所占用的空间会恢复到初始大小,而delete操作不会减少表或索引所占用的空间。
7、不能truncate一个带有外键的表,如果要删除首先要取消外键,然后再删除。

TRUNCATE和DELETE有以下几点区别

1、TRUNCATE在各种表上无论是大的还是小的都非常快。如果有ROLLBACK命令DELETE将被撤销,而TRUNCATE则不会被撤销。

2、TRUNCATE是一个DDL语言,向其他所有的DDL语言一样,他将被隐式提交,不能对TRUNCATE使用ROLLBACK命令。

3、TRUNCATE将重新设置高水平线和所有的索引。在对整个表和索引进行完全浏览时,经过TRUNCATE操作后的表比DELETE操作后的表要快得多。

4、TRUNCATE不能触发任何DELETE触发器。

5、不能授予任何人清空他人的表的权限。

6、当表被清空后表和表的索引讲重新设置成初始大小,而delete则不能。

7、不能清空父表。 TRUNCATE TABLE (schema)table_name DROP(REUSE) STORAGE 在默认是 DROP STORAGE 当使用DROP STORAGE时将缩短表和表索引,将表收缩到最小范围,并重新设置NEXT参数。REUSE STORAGE不会缩短表或者调整NEXT参数在特殊情况下使用 REUSE ST

DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的的删除操作作为事务记录在日志中保存以便进行进行回滚操作。
TRUNCATE TABLE 则一次性地从表中删除所有的数据页并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。

TRUNCATE 是将你的表初始化。假如现在你的表中有10条数据,现在TRUNCATE TABLE 的话,就会将表还原为你最初刚创建好时的状态。表刚创建好时肯定是没有任何数据。因此数据就都没有了。

DELETE TABLE虽然也将你表中的数据清除,但是在你的事务日志文件(LDF)里,还会有相应的记录。没有彻底删除。并且DELETE TABLE 还可以删除指定列,比如我想删除ID为1的列。就可以写: delete 表名 where id=1

 

简单说:

TRUNCATE 删除数据表的结构

DELETE 删除数据表的数据 结构还在

 

如为字段设置了标识列 identity(1,1)

TRUNCATE 删除数据后 再添加数据 就从1开始自增

DELETE 删除数据后 再添加数据 原来的使用的就不能再用了 也就是不是从1开始了 因为原来的占用了

[转载]jQuery EasyUI MC3的应用实例

mikel阅读(1323)

[转载]jQuery EasyUI MC3的应用实例 – wikstone – 博客园.

之前写过一个WebForm和JQuery EasyUI结合的实例,一个用户管理,主要是帮助大家怎样把WebForm及MVC和EasyUI结合起来做项目。这里只有简单实例及入门方法,下面就主要贴图及附源码供大家下载!

这里依然套用疯狂秀才的界面。代码有借鉴博客园一哥们,并进行了修改。

此部分代码可以参考之前WebForm

列表页面:

添加页面:

主要一个了自带控件没有直接使用客户端控件,随后整理全部使用EasyUI控件,表达你提交此处使用了JQuery form提交

下面附上通用js代码:

View Code

<script type="text/javascript">

    $(function () {
        InitGird();
        InitSearch();
    });

    //初始化表格
    function InitGird() {
        $('#tab_list').datagrid({
            title: '用户列表', //表格标题
            url: '@Url.Action("List","User")', //请求数据的页面
            sortName: 'ID', //排序字段
            idField: 'ID', //标识字段,主键
            iconCls: '', //标题左边的图标
            nowrap: false, //是否换行,True 就会把数据显示在一行里
            striped: true, //True 奇偶行使用不同背景色
            collapsible: false, //可折叠
            sortOrder: 'desc', //排序类型
            remoteSort: true, //定义是否从服务器给数据排序
            fit: true,
            fitColumns: true, //自适应
            frozenColumns: [[//冻结的列,不会随横向滚动轴移动
                    {field: 'cbx', checkbox: true },
                    { title: '账号', field: 'UserName', width: 150, sortable: true },
                    { title: '真实姓名', field: 'RealName', width: 150 }
                ]],
            columns: [[
                    { title: '所属角色', field: 'Role', formatter: function (value, rec, index) { return value == 0 ? '管理员' : '普通用户' }, width: 120 },
                    { title: '是否超级管理员', field: 'IsAdmin', formatter: function (value, rec, index) { return value == 0 ? '否' : '是' }, width: 100 },
                    { title: '邮箱地址', field: 'Email', width: 150 },
                    { title: '操作', field: 'ID', width: 80, formatter: function (value, rec) {
                        return '<a style="color:red" href="javascript:;" onclick="EditData(' + value + ');$(this).parent().click();return false;">修改</a>';
                    }

                    }
                ]],
            toolbar: "#toolbar",
            pagination: true, //是否开启分页
            pageNumber: 1,
            pageSize: 10,
            pageList: [10, 20, 30, 40, 50],
            rownumbers: true //行号
        });

    }

    //初始化搜索框
    function InitSearch() {
        $("#ipt_search").searchbox({
            width: 200,
            iconCls: 'icon-save',
            searcher: function (val, name) {
                $('#tab_list').datagrid('options').queryParams.search_type = name;
                $('#tab_list').datagrid('options').queryParams.search_value = val;
                $('#tab_list').datagrid('reload');
            },
            prompt: '请输入要查询的账号'
        });
    }

    //打开添加窗口
    function AddData() {
        var url_str = '@Url.Action("Create","User")';

        $('#Creat_Dialog').load(url_str, function () {
            $(this).dialog({
                title: '添加用户',
                modal: true,
                loadingMessage: '正在加载...',
                buttons: [{
                    text: '提交',
                    iconCls: 'icon-ok',
                    handler: function () {
                        $('#add_form').submit();
                    }
                }, {
                    text: '取消',
                    iconCls: 'icon-cancel',
                    handler: function () {
                        $('#Creat_Dialog').dialog('close');
                    }
                }

                ]
            });
        }).show();
    }

    //打开编辑窗口
    function EditData(id) {
        if (id != undefined) {
            var url = '@Url.Action("Edit","User")/' + id;

            $('#Edit_Dialog').load(url, function () {
                $(this).dialog({
                    title: '编辑用户',
                    modal: true,
                    loadingMessage: '正在加载...',
                    buttons: [{
                        text: '提交',
                        iconCls: 'icon-ok',
                        handler: function () {
                            $('#edit_form').submit();
                        }
                    }, {
                        text: '取消',
                        iconCls: 'icon-cancel',
                        handler: function () {
                            $('#Edit_Dialog').dialog('close');
                        }
                    }]
                });
            }).show();
        }
    }

    //添加AJAX提交
    function ajaxAdd() {
        $('#add_form').ajaxSubmit({
            url: '@Url.Action("Create","User")',
            beforeSubmit: function () {
              //  console.info($('#add_form').form('validate'));
                if ($('#add_form').form('validate') != true) {
                    return false;
                }
                if ($("#add_form").valid() != true) {
                    return false;
                }
                return true;
            },
            success: function (data) {
                if (data == true) {
                    $('#Creat_Dialog').dialog('close');
                    $('#tab_list').datagrid('reload');
                    $.messager.show({
                        title: '提示',
                        msg: '保存成功',
                        timeout: 2000,
                        showType: 'slide'
                    });
                } else {
                    $.messager.show({
                        title: '提示',
                        msg: '保存失败:' + data,
                        timeout: 0,
                        showType: 'slide'
                    });
                }
            }
        });

        return false;
    }
    //编辑AJAX提交
    function ajaxEdit() {
        $('#edit_form').ajaxSubmit({
            url: '@Url.Action("Edit","User")',
            beforeSubmit: function () {
                if ($('#edit_form').form('validate') != true) {
                    return false;
                }
                if ($("#edit_form").valid() != true) {
                    return false;
                }
                return true;
            },
            success: function (data) {
                if (data == true) {
                    $('#Edit_Dialog').dialog('close');
                    $('#tab_list').datagrid('reload');
                    $.messager.show({
                        title: '提示',
                        msg: '保存成功',
                        timeout: 2000,
                        showType: 'slide'
                    });
                } else {
                    $.messager.show({
                        title: '提示',
                        msg: '保存失败:' + data,
                        timeout: 0,
                        showType: 'slide'
                    });
                }
            }
        });

        return false;
    }

    //删除
    function DelData(id) {
        var selected = "";
        if (id <= 0) {
            $($('#tab_list').datagrid('getSelections')).each(function () {
                selected += this.ID + ",";
            });
            selected = selected.substr(0, selected.length - 1);
            if (selected == "") {
                $.messager.alert('提示', '请选择要删除的数据!', 'info');
                return;
            }
        }
        else {
            selected = id;
        }

        if (id != undefined) {
            $.messager.confirm('确认', '确定删除?', function (r) {
                if (r) {
                    var url = '@Url.Action("Delete","User")/' + selected;
                    $.post(url, function () {

                    }).success(function (data) {
                        var msgstr = "删除成功";
                        if (data != true) {
                            msgstr = "删除失败" + data;
                            $.messager.show({
                                title: '提示',
                                msg: msgstr,
                                timeout: 0,
                                showType: 'slide'
                            });
                        } else {
                            $('#tab_list').datagrid('reload');
                            selected = '';
                            $.messager.show({
                                title: '提示',
                                msg: msgstr,
                                timeout: 3000,
                                showType: 'slide'
                            });
                        }

                        $('#tab_list').datagrid('reload');
                    }).error(function () {
                        $.messager.alert('错误', '删除发生错误');
                    });

                }
            });
        }
    }

</script>

今天简单就到这里吧!QQ群:92257772 希望大家能够共同学习。

下载链接

[转载]jQuery实现表格按列字母或数字排序

mikel阅读(1761)

[转载]jQuery实现表格按列字母或数字排序 – 海之澜 – 博客园.

最近做的一个项目中需要自己写个表格排序的功能,于是就上网收集了一下,主要原理就是JQuery操作表格

JQuery代码如下:

$(function () {
$('#tblGrid').each(function () {
var $table = $(this); //将table存储为一个jquery对象

$('thead td', $table).each(function (column) {
var findSortKey;
if ($(this).is('.sort-alpha')) { //按字母排序
findSortKey = function ($cell) {
return $cell.find('sort-key').text().toUpperCase() + '' + $cell.text().toUpperCase();
};
} else if ($(this).is('.sort-numeric')) { //按数字排序
findSortKey = function ($cell) {
var key = parseFloat($cell.text().replace(/^[^\d.]*/, ''));
return isNaN(key) ? 0 : key;
};
}

if (findSortKey) {
$(this).addClass('clickable').hover(function () { $(this).addClass('hover'); }, function () { $(this).removeClass('hover'); }).click(function () {
//反向排序状态声明
var newDirection = 1;
if ($(this).is('.sorted-asc')) {
newDirection = -1;
}
var rows = $table.find('tbody&gt;tr').get(); //将数据行转换为数组
$.each(rows, function (index, row) {
row.sortKey = findSortKey($(row).children('td').eq(column));
});
rows.sort(function (a, b) {
if (a.sortKey &lt; b.sortKey) return -newDirection; if (a.sortKey &gt; b.sortKey) return newDirection;
return 0;
});
$.each(rows, function (index, row) {
$table.children('tbody').append(row);
row.sortKey = null;
});

$table.find('thead td').removeClass('sorted-asc').removeClass('sorted-desc');
var $sortHead = $table.find('thead td').filter(':nth-child(' + (column + 1) + ')');
//实现反向排序
if (newDirection == 1) {
$sortHead.addClass('sorted-asc');
} else {
$sortHead.addClass('sorted-desc');
}

//移除已排序的列的样式,添加样式到当前列
$table.find('td').removeClass('sorted').filter(':nth-child(' + (column + 1) + ')').addClass('sorted');
$table.trigger('repaginate');
});
}
});
});
});

Html代码如下:


&nbsp;
<table id="tblGrid">
<thead>
<tr>
<td style="width: 10%;">员工工号</td>
<td style="width: 10%;">员工姓名</td>
<td style="width: 15%;">职务名称</td>
<td class="sort-numeric" style="width: 10%;">得分</td>
<td class="sort-alpha" style="width: 10%;">绩效考核等级

(直接主管)</td>
<td style="width: 25%;">事例说明</td>
<td class="sort-alpha" style="width: 10%;">绩效考核等级

(上级主管)</td>
<td style="width: 10%;">绩效考核等级

(部门主管)</td>
</tr>
</thead>
<tbody><!--#RowBegin#-->
<tr>
<td height="28px"></td>
<td>张三</td>
<td>客服支持</td>
<td></td>
<td class="director_1">优秀</td>
<td>李四 直接主管考评信息</td>
<td>待改进</td>
<td><select name="Table:model:RANK:0"> <option value="">-请选择-</option></select>
<select name="Table:model:RANK:0"> <option value="优秀">优秀</option></select>
<select name="Table:model:RANK:0"> <option value="优良">优良</option></select>
<select name="Table:model:RANK:0"> <option value="良好">良好</option></select>
<select name="Table:model:RANK:0"> <option selected="selected" value="待改进">待改进</option></select>
<select name="Table:model:RANK:0"> <option value="不胜任">不胜任</option></select></td>
</tr>
<tr>
<td height="28px"></td>
<td>王五</td>
<td>客服支持</td>
<td></td>
<td class="director_2">优良</td>
<td>事例说明</td>
<td>优良</td>
<td><select name="Table:model:RANK:1"> <option value="">-请选择-</option></select>
<select name="Table:model:RANK:1"> <option value="优秀">优秀</option></select>
<select name="Table:model:RANK:1"> <option selected="selected" value="优良">优良</option></select>
<select name="Table:model:RANK:1"> <option value="良好">良好</option></select>
<select name="Table:model:RANK:1"> <option value="待改进">待改进</option></select>
<select name="Table:model:RANK:1"> <option value="不胜任">不胜任</option></select></td>
</tr>
<tr>
<td height="28px"></td>
<td>周氏</td>
<td>客服支持</td>
<td></td>
<td class="director_3">优秀</td>
<td>直接主管考评信息</td>
<td>优秀</td>
<td><select name="Table:model:RANK:2"> <option value="">-请选择-</option></select>
<select name="Table:model:RANK:2"> <option selected="selected" value="优秀">优秀</option></select>
<select name="Table:model:RANK:2"> <option value="优良">优良</option></select>
<select name="Table:model:RANK:2"> <option value="良好">良好</option></select>
<select name="Table:model:RANK:2"> <option value="待改进">待改进</option></select>
<select name="Table:model:RANK:2"> <option value="不胜任">不胜任</option></select></td>
</tr>
<!--#RowEnd#--></tbody>
</table>

css:


 

利用JQuery的ready事件即可实现排序功能,

页面效果如图:

点击查看源代码SortTable.rar

[转载]LINQ to SQL实战(3) N层架构中使用LINQ联合查询多表结果集的返回

mikel阅读(1036)

[转载]LINQ to SQL实战(3) N层架构中使用LINQ联合查询多表结果集的返回 – C#|DOTNET – yaosansi’s Blog.

转载请标明出处: http://www.yaosansi.com

原文:http://www.yaosansi.com/post/1388.html

首先,我们先来了解一些知识点。

1.匿名类型的传递

       static void Main(string[] args)
        {
            var User = GetAnonymous().Cast(new { UserName = "", LastLoginIp = "" });
            Console.Write(User.UserName);
        }

        static object GetAnonymous()
        {
            var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" };
            return User;
        }

当我们定义一个匿名类型,只能通过object类型传递,传递后编译器将无法获悉匿名类型的实际类型。

这行可以通过Cast扩展方法来进行强制转换。以下是Cast方法的原型。

        public static T Cast<T>(this object o, T t)
        {
            return (T)o;
        }

2.如何生成匿名类型的List?

           var User = GetAnonymous().Cast(new { UserName = "", LastLoginIp = "" });
           var list = new List<???>();
原理和上面一致。
            var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" };
            var list = User.MakeList();
            list.Add(User);
            Console.Write(list[0].UserName);

我们再来看看MakeList()方法:

        public static List<T> MakeList<T>(this T t)
        {
            return new List<T>();
        }

当然,你可能想到上面的方法还不够完美,需要在List中Add一个User,于是有了下面的方法:
        public static List<T> MakeList<T>(this T t,params T[] items)
        {
            return new List<T>(items);
        }
这时调用的时候可以写成:
            var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" };
            var list = User.MakeList(User);
            Console.Write(list[0].UserName);

这回我们切入正题,来了解一下LINQ中是怎样多表查询的。

    var q =
    from p in db.Products
    where p.Supplier.Country == "USA" && p.UnitsInStock == 0
    select p;


以上的查询是两个有关系的表,并且返回的只是一个表的内容,
这种情况下可以在数据层中返回强类型的List。如:

 public List<Products> SelectProducts()
 {
      var q =
      from p in db.Products
      where p.Supplier.Country == "USA" && p.UnitsInStock == 0
      select p;
      return q.ToList<Products>;
 }

如果返回的结果集是两个以上表的时候,那该如何传递呢?

聪明的你一定想到了,如果返回的是单行数据的结果集就可以我们前面提到的
使用 匿名类型的传递 得到我们需要的结果.
 public object SelectProducts()
 {
      var q =
      from p in db.Products
      where p.Supplier.Country == "USA" && p.UnitsInStock == 0
      select new {p.UnitsInStock,p.Supplier.Sid};
      var result = q.Single();
      return result;
 }
但这个前提是业务逻辑层需要知道数据层的匿名类型中的具体类型。
这样分层的意义也就不大了。这并不是我们想要的。
而且返回多行数据的结果集时用 匿名的List类型 的方法经实验也失败了。
这就意味着本文开篇的两种传递匿名类型的方法都行不通。

方法一:
自定义与返回类型相同结构的类,
        public class CustomQuery
        {
            public uint UnitsInStock { get; set; }
            public int Sid { get; set; }
        }
这样在查询结果为多个表的结果集时,就可以解决了。
由于需要知道返回的匿名类型,除了不符合多层以外,还需要额外定义一个类。
但这样确时可以使用强类型返回我们所需要的结果。

方法二:
使用System.Func委托 (参考:Returning var from a method in C# 3.0

数据层:
public IEnumerable<TProjection> GetCustomersWithOrders<TProjection>(Func<Customer, IEnumerable<Order>, TProjection> projection) {
    return from customer in _customers
           let customerOrders = from order in _orders
                                where order.CustomerID = customer.ID
           select projection(customer, customerOrders);
}

业务逻辑层:
var results = GetCustomersWithOrders((customer, orders) =>
 new {
                 Name = customer.Name,
                 OrderCount = orders.Count()
      });

这样返回的结果在业务逻辑层里仍然是真正的匿名类型,可以直接使用了。

方法三:

使用存储过程或视图。

[转载]LINQ to Entities 实现sql 关键字"In"方式总结

mikel阅读(1041)

[转载]LINQ to Entities 实现sql 关键字”In”方式总结 – ejiyuan – 博客园.

在LINQ to Entities中没有办法再像 LINQ to SQL 中一样使用 Contains 的方法来实现SQL “in” 关键字

下面代码在 LINQ to SQL 中可行 在LINQ to Entities却无法运行:

var s = db.Account.Select(c => c.ID);
var ret 
=(from t in db.Profile
where s.Contains(t.ID)
select t).ToList();

 

替代方法1:使用方法Any

var ids=db.Account.Select(c => c.ID);
var ret 
= (from t in db.Profile where ids.Any(c=>c==t.UserID) select t).ToList();

使用方法Any替换法搞了好久都没法实现直接对数组Any,下列代码仍无法执行:

int[] ids = new int[]{10101,10005,10007};
var ret 
= (from t in db.Profile where ids.Any(c=>c==t.UserID) select t).ToList();

于是继续Goolge寻找第二种方法,在MSDN论坛上找一个构造Lambda语句的方法
替代方法2:构造Lambda语句

复制代码

        private static Expression<Func<TElement, bool>> BuildWhereInExpression<TElement, TValue>(Expression<Func<TElement, TValue>> propertySelector, IEnumerable<TValue> values)
{
ParameterExpression p 
= propertySelector.Parameters.Single();
if (!values.Any())
return e => false;

var equals = values.Select(value => (Expression)Expression.Equal(propertySelector.Body, Expression.Constant(value, typeof(TValue))));
var body 
= equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));

return Expression.Lambda<Func<TElement, bool>>(body, p);
}

复制代码

调用方法:

int[] ids = new int[]{10101,10005,10007};
db.Profile.Where(BuildWhereInExpression
<Profile,int>(v=>v.Id,ids);

该方法可也扩展为:

        public static IQueryable<TElement> WhereIn<TElement, TValue>(this IQueryable<TElement> source, Expression<Func<TElement, TValue>> propertySelector, params TValue[] values)
{
return source.Where(BuildWhereInExpression(propertySelector, values));
}

这样就可以直接使用下列方法调用

string[] ids = new string[]{10101,10005,10007};
db.Profile.WhereNotIn(c 
=> c.Id,ids);

后来又看到网上有这样的解决办法
替代方法3:字符串构造
这个方法比较简单

string[] ids = new string[]{10101,10005,10007};
string csvIds = string.Join(,, ids.Cast<string>().ToArray());
db.Profile.Where(
it.Id in {+csvIds+});

it是什么这里就不用说了吧!

[转载]ASP.NET MVC 3的分部视图

mikel阅读(1816)

[转载]ASP.NET MVC 3的分部视图 – R-King – 博客园.

1、什么是分部视图,我们应该什么时候应该用?

作为一个对ASP.NET MVC 模型很熟悉的开发者,他们自然想创建一个内容和代码都可以重用的组件,在web 窗体,我们可以创建一个web用户控件或web服务器控件。但是在MVC,我们应该用分部视图,在这个概念的角度看,对任何情景的应用情景都应该有用。
在应用程序中,每一页上都显示这个股票行情
在应用程序中,一个日历控件显示在多个页面中
一个登录框
用于在多个页面上的社交网络组件,如Facebook的Like按钮。
虽然ASP.NET MVC 的分部视图,在语法和功能这两个不同的角度,理论上可以理解为用户控件。WEB用户控件在WEB窗体中使用ViewState、PostBacks, and Events 。而在MVC的分部视图,不使用任何上述技术管理状态。正如ASP.NET Web用户控件做的,分部视图,可以挖掘到你的应用程序以及其他应用程序组件之间的数据共享中的模型。
2、分部视图的渲染
ASP.NET MVC3的分部视图周昂,允许开发人员用精确和简洁的Razor syntax语法(或ASPX)创建可重复使用的内容模块。呈现分部视图的语法被作为一个HTML辅助实现。
 Html.Partial辅助呈现分部视图名为“_FeaturedProduct”内联。所有重载方法的第一个参数为@Html.Partial 你期望的视图名称或者分部视图的名字,没有文件扩展名。
例如,一个@Html.Partial辅助假定视图放在 \Views\Shared\ 的文件夹下。其他的 @Html.Partial方法重载允许你在各个视图之间传递ViewData或者 ViewBag对象.
下面的代码演示调用呈现分部视图的特点。
<div> @Html.Partial("_FeaturedProduct") </div>

 

分部视图可以在Layout Page布局页面呈现。
也有一些情况下,你可能要另外一种方式实现,比如直接写入HTTP响应流,而不是局部视图渲染结果。
<div> @Html.RenderPartial("_FeaturedProduct") </div>

使用Html.RenderPartial流图像或其他元素,媒体中心或更快的下载时间是非常重要的。

 

3、创建一个局部视图

不管是主视图还是分部视图都是.cshtml 的文件,其中分部视图的不同之处是在于文件放在:\Views\Shared\ 文件下。通过在解决方案资源管理器上下文菜单中使用“添加新视图”对话框来访问\Views\Shared 文件节点。添加新的视图模板“对话框提供了用于创建您的部分视图,特别注意,包括选项的选择。不要忘记检查“作为一个局部视图”创建或你会结束大量的代码删除。

 

一旦你创建的视图,你可以开始通过简单的编辑文件定制。删除或修改视图的代码捆绑在一起。下面所示的代码(_FeaturedProduct.cshtml)是默认视图模板创建相同的代码,我们可以修改,以显示不同的特色产品:

<div>
<div>
<h2>Our Featured product:

@ViewBag.FeaturedProduct.Name</h2>
</div>
<div>
<h3>Now discounted to $@String.Format("{0:F}", ((decimal)ViewBag.FeaturedProduct.Price)-100)</h3>
</div>
<div>@Html.ActionLink("Featured Product Details", "Details", new { id = ViewBag.FeaturedProduct.ProductId })</div>
<div><img class="featuredProduct" src="@Href(" alt="Featured Product" /></div>
</div>

和强类型一样,强类型分部视图也支持点标记语法和访问模型,ViewBag,ViewData的其他类,并专门设计数据共享。

我们阅读上面的代码,我们应该很明确,分部视图和常规视图的语法没有区别。

重要的是没有相关语法关于如何使用分部视图。然而,考虑分部视图和常规视图之间的一致性,特别是当我们需要在它们之间共享数据。

4、主视图与分部视图的数据共享

应用程序组件之间的数据传递,这是一个普遍的现象,MVC,视图和控制器这些组件也一样。 如前所述,你可以使用ViewBag或ViewData的类进行数据的共享。首先,介绍ViewBag的ViewData几个关键字:

ViewData的是以前发布的版本的;,ViewBag与MVC3一起发布的。

ViewData的可以包含任何类型的数据在一个键—值对格式。即,ViewData[“Message”] = “Welcome”;

ViewBag对象的ViewData对象的包装,并允许开发人员编写他们使用强类型的语法。

ViewBag对象可以通过简单地设置在一个更流畅的语法属性扩展。即· ViewBag.Customer = new Customer(1,”Smith”);

 

如果在一个控制器的代码使用ViewBag,或ViewData的类,这些类将可视图的整个生命周期,而且包括其分部视图。

可取的对象是的ViewBag。由于其更加流畅和动感的语法,还有复杂的对象可以很容易地在组件之间共享。下面的示例演示设置在控制器的ViewBag对象,它会提供所有必要的组件:

ProductModel productModel = new ProductModel(); public ActionResult Index() { ViewBag.FeaturedProduct = new FeaturedProduct(105, "The Most Awesome Bike Ever!", 1000.00M, "bike4.png"); return View(productModel.Products); }

访问视图里面的ViewBag或部分使用语法如下:

@ViewBag.FeaturedProduct.Name

5、总结

部分视图重用HTML和Razor 语法,具有很好的数据共享。

 

6、资料来源

Introducing Razor

Introducing MVC Development w/the Razor View Engine

Razor View Syntax