[转载]SQL语句行列转换(附带数据库、表、视图操作)

mikel阅读(940)

[转载]SQL语句行列转换(附带数据库、表、视图操作) – 温度 – 博客园.

本来只是想解决怎么把数据的行和列进行转换的,但最近觉得一些数据库SQL语句的操作,很久没用了,有点陌生。所以也就随笔记录一些简单但很基本的操作。

 

我的数据库是MSSQL2005.

 

第一部分主要的操作包含:数据库的创建、删除,表的增、删、改,表中数据的增、删、改、查,视图的操作。

 

 1 --查询数据库是否存在
 2 if exists ( select * from sysdatabases where [name]='TestDB')
 3 print 'Yes, the DB exists'
 4 else
 5 print 'No, need a new one?'
 6 
 7 --新建一个数据库
 8 create database TestDB on
 9 (
 10     name = 'TestData',
 11     filename = 'G:\DBS\KeyTest.mdf',
 12     size = 3,
 13     filegrowth = 2
 14 )
 15 log on
 16 (
 17     name = 'TestLog',
 18     filename = 'G:\DBS\KeyTest.ldf',
 19     size = 3,
 20     filegrowth = 10
 21 )
 22 
 23 --drop database TestDB
 24 
 25 use TestDB
 26 go
 27 
 28 --新建一个表
 29 create table [Scores]
 30 (
 31     [ID] int identity(1,1) primary key,
 32     [Student] varchar(20) ,
 33     [Subject] varchar(30),
 34     [Score] float
 35 )
 36 
 37 --drop table [Scores]
 38 
 39 --修改表中的一列
 40 alter table Scores alter column [Student] varchar(20) not null
 41 
 42 --新增一列
 43 alter table Scores add Birthday datetime 
 44 
 45 --删除一列
 46 alter table Scores drop column Birthday
 47 
 48 --往表中插入单条数据,方法1:带列名
 49 insert into Scores(Student,Subject,Score)
 50 values('张三','语文','90')
 51 
 52 --往表中插入单条数据,方法2:不带列名,但要求值的类型要和列字段类型对应
 53 insert into Scores
 54 values('张三','英语','95')
 55 
 56 --插入多条数据:用union或者union all
 57 insert into Scores(Student,Subject,Score)
 58 select '李四','语文','89'
 59 union all
 60 select '李四','英语','78'
 61 
 62 --删除表中数据,没有条件时,删除所有
 63 delete from Scores where ID in(7,8)
 64 
 65 --修改表中数据
 66 update Scores 
 67 set Student='王五',Score='94'
 68 where ID=10
 69 
 70 --查看数据
 71 select * from Scores
 72 
 73 --查看表中最大的identity值
 74 select @@identity
 75 
 76 --或者利用dbcc命令查看表中最大的identity值
 77 dbcc checkident('Scores',noreseed)
 78 
 79 --创建视图,全部省略视图的属性列名,由子查询目标列的字段组成
 80 create view StudentView
 81 as
 82 select Student,Subject,Score
 83 from Scores
 84 
 85 --加上with check option,以后对视图的操作(增,改,删,查)都会自动加上where ID>3
 86 /*
 87 create view StudentView
 88 as
 89 select Student,Subject,Score
 90 from Scores
 91 where ID>3
 92 with check option
 93 */
 94 
 95 --创建视图,全部定义属性列名,需要定义列名的情况:
 96 ----某个目标列(子查询)不是单纯的属性列,而是聚集函数或列表达式
 97 ----多表连接时选出了几个同名列
 98 ----需要在视图中为某个列启用新的更合适的名字
 99 create view IS_Student(Student,Subject,MaxScore)
100 as
101 select Student,Subject,Score
102 from Scores
103 where Score=(select max(Score) from Scores)
104 
105 
106 --查询视图,和基本表完全样,只不过如果视图中有with check option,会自动加上那个条件
107 select * 
108 from StudentView
109 
110 --查询自定义列名的视图
111 select * 
112 from IS_Student
113 
114 --对视图的insert/delete/update,和对基本表的操作一样,并且最终都是用RDBMS自动转换为对基本表的更新
115 --并不是所有的视图都是可更新的,因为有些视图的更新不能有意义的转换成对相应基本表的更新
116 
117 --删除视图
118 drop view StudentView

 

第二部分,这次练习的主题。

 

【一】行转列

 

1,查询原始的数据

 

/***这次练习的主题,行转列,列转行***/
select * from Scores

 

 

2,得到姓名,通过group by

 

select Student as '姓名'
from Scores
group by Student
order by Student

 

 

3,再加上max, case……when

 

select Student as '姓名',
max(case Subject when '语文' then Score else 0 end) as '语文' ,--如果这个行是“语文”,就选此行作为列
max(case Subject when '英语' then Score else 0 end ) as '英语'
from Scores
group by Student
order by Student

 

 

 

 

查看其它资料时,看到另外一种方法,用pivot

 

--group by, avg/max, pivot。这里用max和avg,结果都一样,有什么区别吗?有点不明白
--参考网上的资料,用法如下
/*
pivot(
  聚合函数(要转成列值的列名)
  for 要转换的列
  in(目标列名)
  )
*/
select Student as '姓名',
avg(语文) as '语文',
avg(英语) as '英语'
from Scores
pivot(
    avg(Score) for Subject 
    in (语文,英语)
    )as NewScores
group by Student
order by Student asc

 

[转载]Asp.net中服务端控件事件是如何触发的?

mikel阅读(1035)

[转载]Asp.net中服务端控件事件是如何触发的? – @Dylan – 博客园.

初学ASP.NET的时候,曾被各种控件的强大功能所折服。当然,也很容易被搞晕,仅仅记住那些控件的名字都不是一件简单的事儿,何况还有那么多的属性、事件、功能、配置步骤……哈哈。后来越发觉得这些东西确实没啥价值,在企业级开发中很少用到。

写本文的目的并不是要“贬低”或者刻意“排斥”webform中的服务端控件,这里对其优劣也不做过多的讨论。

不过有情提示初学者:其实很多控件的用法都差不多,掌握一种后,再去使用其他的会相对比较容易。例如会用GridView之后,再 去用ListView绝对不是难事。切勿“浮于控件表面”,因为你一旦形成了某种思维方式,以后会很难提高。当然,当你慢慢理解了web的本质和这些控件 的内部机制,回头再去看那些东西,会觉得实在太简单了。这又是一个“先磨刀还是先砍柴”的问题了。

 

我们经常拖动一个服务器控件到aspx页面上(例如一个Button按钮),然后双击,就会看到后台代码中注册了一个click事件。或者你也可以 在控件上“右键”–》“属性”,然后找到“闪电图标”–事件,然后注册相应的事件。这就是传说中的webform的“事件驱动机制”。如果你曾经接触 过VB或者windows开发,或许会倍感温馨。

那这些事件,到底是如何触发的呢?我能否模拟出来呢?为啥我有时候点击了Button按钮却没有触发后台事件?

ASP.NET 中在客户端触发服务端事件分为两种情况:

一. WebControls中的Button 和HtmlControls中的Type为submit的HtmlInputButton

这两种按钮最终到客户端的表现形式为:

< input name="Submit1" id="Submit1" type="submit" value=”Submit”>

这是Form表单的提交按钮,点击以后会作为参数发送到服务端,参数是这样的: 控件的name属性=控件的value值,对应上面的例子就是:Submit1= Submit。 服务端会根据接收到的控件的name属性的这个key来得知是这个按钮被点击了,从而在服务端触发这个按钮的点击事件。

二. HtmlControls 中的 Type为button的HtmlInputButton 和其它所有的控件事件,比如LinkButton点击,TextBox的Change事件等等:

这些事件在客户端产生后会经过一个统一的机制发送到服务端。

1. 首先asp.net页框架会使用两个Hidden域来存放表示是哪个控件触发的事件,以及事件的参数:

< !-- 表示触发事件的控件,一般是这个控件的name -->

< input type="hidden" name="__EVENTTARGET" value="" />
< !-- 表示触发事件的参数,一般是当某个控件有两个以上的事件时,用来区别是哪个事件 -->

< input type="hidden" name="__EVENTARGUMENT" value="" />

2. 服务端会生成一个JavaScript的方法来处理所有这些事件的发送,这段代码是:

< script type="javascript">
  < !--

  function __doPostBack(eventTarget, eventArgument) {

  var theform = document.WebForm2;

  theform.__EVENTTARGET.value = eventTarget;

  theform.__EVENTARGUMENT.value = eventArgument;

  theform.submit();

  }

  // -->

  < /script>

3. 每个会引发服务端事件的控件都会在响应的客户端事件中调用上面的代码

浏览器只认html、js、css、图片等静态内容,不管你什么aspx、php、jsp页面最终都会变成html,呈现给用户

比如,HtmlControls 中的 Type为button的HtmlInputButton的点击事件

< !--客户端的点击事件调用__doPostBack,eventTarget 参数为'Button2',表示是name为'Button2’控件触发的事件,eventArgument 为空,表示这个Type为button的HtmlInputButton只有一个客户端触发的服务端事件-->
< input language="javascript" onclick="__doPostBack('Button2','')" name="Button2" id="Button2" type="button" value="Button" />

 

又比如,TextBox控件的Change事件

< !--客户端的onchange事件调用__doPostBack,eventTarget 参数为’TextBox1’,表示是name为’TextBox1’控件触发的事件,而TextBox控件只有一个客户端触发的服务端事件TextChanged,故服务器就会去触发这个TextBox的TextChanged事件-->
< input name="TextBox1" type="text" id="TextBox1" onchange="__doPostBack('TextBox1','')" language="javascript" />

4. 客户端触发事件后调用__doPostBack方法,将表示触发的控件源的eventTarget 和事件参数eventArgument分别付给两个隐藏域__EVENTTARGET和__EVENTARGUMENT,然后提交Form,在服务端根据 __EVENTTARGET和__EVENTARGUMENT来判断是哪个控件的什么事件触发了。

 

5.既然了解了__doPostBack这个“著名”的函数,那么我们当然也可以想办法“盗链”了。论坛上经常有很多人问,如何用普通的html控 件(标签)和js调用后台的方法/激发后台事件。呵呵。使用“盗链”不久可以了吗?当然,还有很多实现方式,这里我就不再赘述了。

 

说了这么多,相信读者已经理解了asp.net中所谓的“事件机制”了。还是那句话,web开发,无非是“请求/处理/响应”

[转载]ASP.NET MVC中使用jQuery时的浏览器缓存问题

mikel阅读(889)

[转载]大叔手记(20):ASP.NET MVC中使用jQuery时的浏览器缓存问题 – 汤姆大叔 – 博客园.

介绍

尽管JQuery在浏览器ajax调用的时候对缓存提供了很好的支持,还是有必要了解一下如何高效地使用http协议。

首先要做的事情是在服务器端支持HTTP GET,定义不同的URL输出不同的数据(MVC里对应的就是action)。如果要使用同一个地址获取不同的数据,那就不对了,一个HTTP POST也不行因为POST不能被缓存。许多开发人员使用POST主要有2个原因:明确了数据不能被缓存,或者是避免JSON攻击(JSON返回数组的时 候可以被入侵)。

缓存解释

JQuery全局对象里的ajax方法提供了一些options来支持缓存和Conditional GETs功能。

$.ajax({
    ifModified: [true|false],
    cache: [true|false],
});

ifModified选项定义的是在ajax调用的时候是否支持Conditional GETs功能。JQuery会自动帮我们处理服务器端返回的名为Last-Modified的header值,然后在随后的请求里的header里发送 If-Modified-Since。这需要我们的MVC Controller要实现Conditional GETs功能才能用。Conditional GETs功能在http缓存上下文中用于重新验证缓存中过期的条目。如果jQuery认为一个条目已经过期了,它首先会请求服务器使用 Conditional GETs功能重新验证该条目,如果服务器返回状态码304(Not modified),jQuery会重新使用缓存里的该项目,这样的话,我们可以节约很多流量去下载页面内容。

cache选项基本上是覆盖服务器端返回的http header里的所有关于缓存的设置,如果设置cache选项为false的话,jQuery会在请求的URL后面附件一个时间戳,以便区分之前的URL 地址,这样没错请求的内容都是最新的,也就是说浏览器每次接收的都是新地址,自然返回的都是最新数据。

让我们来看几个场景:

服务器端响应里设置No-Cache

服务器端为王,如果服务器端明确定义了response响应不能被缓存的话,jQuery也无能为力。ajax里的cache选项将被忽略。

JS代码:

$('#nocache').click(function () {
    $.ajax({
        url: '/Home/NoCache',
        ifModified: false,
        cache: true,
        success: function (data, status, xhr) {
            $('#content').html(data.count);
        }
    });
});

C#代码:

public ActionResult NoCache()
{
   // 禁用缓存
   Response.Cache.SetCacheability(HttpCacheability.NoCache);
   return Json(new { count = Count++ }, JsonRequestBehavior.AllowGet);
}

服务器端响应里设置过期时间

服务器端设置过期时间用于缓存数据,该条目在客户端将依据过期时间被缓存。

JS代码:

$('#expires').click(function () {
    $.ajax({
        url: '/Home/Expires',
        ifModified: false,
        cache: true,
        success: function (data, status, xhr) {
            $('#content').html(data.count);
        }
    });
});

C#代码:

public ActionResult Expires()
{
    Response.Cache.SetExpires(DateTime.Now.AddSeconds(5));
    return Json(new { count = Count++ }, JsonRequestBehavior.AllowGet);
}

客户端从来不缓存数据

客户端决定每次都要最新的数据(不能使用缓存),也就是说ajaxi里的cache选项设置为false,不管服务器端如何定义,jQuery每次请求的URL地址都是唯一不同的,目的是每次都获取最新的内容。

JS代码:

$('#expires_nocache').click(function () {
    $.ajax({
        url: '/Home/Expires',
        ifModified: false,
        cache: false, // 这里是关键
        success: function (data, status, xhr) {
            $('#content').html(data.count);
        }
    });
});

C#代码:

public ActionResult Expires()
{
    // 不管服务器端怎么设置都没用
    Response.Cache.SetExpires(DateTime.Now.AddSeconds(5));
    return Json(new { count = Count++ }, JsonRequestBehavior.AllowGet);
}

服务器端和客户端使用Conditional Gets功能验证缓存数据

客户端将条目放在缓存里,在过期之后重新验证。服务器端必须实现Conditional GET功能(使用ETags或者last modified的header)。

JS代码:

$('#expires_conditional').click(function () {
    $.ajax({
        url: '/Home/ExpiresWithConditional',
        ifModified: true, // 这里是关键
        cache: true,
        success: function (data, status, xhr) {
            $('#content').html(data.count);
        }
    });
});

C#代码:

public ActionResult ExpiresWithConditional()
{
    if (Request.Headers["If-Modified-Since"] != null && Count % 2 == 0)
    {
        return new HttpStatusCodeResult((int)HttpStatusCode.NotModified);
    }

    Response.Cache.SetExpires(DateTime.Now.AddSeconds(5));
    Response.Cache.SetLastModified(DateTime.Now);

    return Json(new { count = Count++ }, JsonRequestBehavior.AllowGet);
}

上述MVC action中的代码只是一个例子(非真实代码),在真实的实现中,服务器端应该能够知道数据自从上次响应以后是否被修改过。

总结

详细通过这4个场景,大家应该了解了ajax请求的缓存技术了吧,我就不做总结了。

英文原文来自:http://weblogs.ASP.NET/cibrax/archive/2012/02/10/hacking-the-browser-cache-with-jquery-and-asp-net-mvc.aspx

同步与推荐

本文已同步至目录索引:《大叔手记全集》

大叔手记:旨在记录日常工作中的各种小技巧与资料(包括但不限于技术),如对你有用,请推荐一把,给大叔写作的动力。

[转载]简单代码生成器原理剖析

mikel阅读(882)

[转载]简单代码生成器原理剖析 – 36氪 – 博客园.

上篇文章(深入浅出三层架构)分析了简单三层架构的实现。包括Model,DAL(数据访问层),BLL(业务逻辑层)的实现。

实际开发中,由于重复代码的操作,会花费大量时间,如果以代码生成器来自动生成三层架构代码,即节省精力,又可以节省大量的时间来做其他业务逻辑的代码,提高开发效率。

常用的代码生成器有:动软,CodeSmith 等。

简单代码生成器的基本功能描述:

一键生成Model,DAL,BLL,包括对应数据库中表的Model的自动生成,包括生成属性、添加、修改、删除、查询。

界面展示:

生成器开发技术要点:

  1. 查询系统视图:INFORMATION_SCHEMA.TABLES、 INFORMATION_SCHEMA.COLUMNS  可以获得数据库中表、列的相关信息。
  2. 字符串的拼接:StringBuilder的使用,其AppendLine()会自动换行。
  3. 将字符串写入文本文件:File.WriteAllText()
  4. 为了降低开发难度,先假设条件多一些,如表的主键都为Id,且自动增长,之后再逐步完善

关键代码:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;

namespace CodeGenerator
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
 /// 执行ExecuteDataTable(),得到DataTable
 /// </summary>
 /// <param name="cmdText"></param>
 /// <param name="parameters"></param>
 /// <returns></returns>
        public  DataTable ExecuteDataTable(string cmdText,
            params SqlParameter[] parameters)
        {
            using (SqlConnection conn=new SqlConnection(txtConnStr.Text))
            {
                conn.Open();
                using(SqlCommand cmd=conn.CreateCommand())
                {
                    cmd.CommandText = cmdText;
                    cmd.Parameters.AddRange(parameters);
                    using (SqlDataAdapter adapter=new SqlDataAdapter (cmd))
                    {
                        DataTable dt = new DataTable();
                        adapter.Fill(dt);
                        return dt;
                    }
                }
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            txtConnStr.Text = @"Data Source=EYES\SQLEXPRESS;Initial Catalog=SanCeng;Integrated Security=True";
        }

        private void btnConnStr_Click(object sender, EventArgs e)
        {

            //清空
            clbTables.Items.Clear();
            //查询系统试图
            string sql = "select * from INFORMATION_SCHEMA.TABLES";
            DataTable dt = ExecuteDataTable(sql);
            //根据系统视图取得TABLE_NAME
            foreach (DataRow row in dt.Rows)
            {
                string tablename = Convert.ToString(row["TABLE_NAME"]);
                clbTables.Items.Add(tablename);
            }

        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            //连接字符串
 //方法AppendLine()追加字符串且自动执行换行

            foreach (string tableName in clbTables.CheckedItems)
            {
                string sql = "select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=@TABLE_NAME ";
                DataTable dt = ExecuteDataTable(sql,new SqlParameter("TABLE_NAME",tableName));

                #region  生成Model
                CreatModel(tableName, dt);
                #endregion

                #region 生成DAL
          

                CreatDAL(tableName, dt);
                #endregion
                #region 生成BLL
                CreatBLL(tableName, dt);
                #endregion
            }
        }

        private static void CreatDAL(string tableName, DataTable dt)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using System.Linq;");
            sb.AppendLine("using System.Text;");
            sb.AppendLine("using 三层架构Demo.Model;");
            sb.AppendLine("using System.Data.SqlClient;");
            sb.AppendLine("using System.Data;");
            sb.AppendLine("namespace 三层架构Demo.DAL");
            sb.AppendLine("{");
            sb.AppendLine("class " + tableName + "DAL");
            sb.AppendLine("{");
            //去掉Id
            sb.AppendLine(" public int Addnew(" + tableName + " model)");
            sb.AppendLine("{");
            List<String> cols = new List<string>();
            List<String> parameters = new List<string>();
            foreach (DataRow row in dt.Rows)
            {
                string col = Convert.ToString(row["COLUMN_NAME"]);
                string parameter = "";
                if (col.ToLower()!="id")
                {
                        parameter= "@" + Convert.ToString(row["COLUMN_NAME"]);
                        cols.Add(col);
                        parameters.Add(parameter);
                }
                //parameters.Add(parameter)放外面加上一个NULL,所以会多出一个逗号
 // parameters.Add(parameter);
                
            }

            sb.AppendLine("string sql = \"insert into " + tableName + "(" + String.Join(",", cols) + ") output inserted.Id values(" + String.Join(",", parameters) + ")\";");
            sb.AppendLine("object obj= SQLHelper.ExecuteScalar(sql");

            foreach (DataRow row in dt.Rows)
            {
                string col = Convert.ToString(row["COLUMN_NAME"]);
                if (col.ToLower() != "id")
                {
                    sb.AppendLine(",new SqlParameter(\"" + col + "\",model." + col + ")");
                }
                
            }
            sb.AppendLine(");");
            sb.AppendLine("return Convert.ToInt32(obj);");
            sb.AppendLine("}");
            //Delete方法
          
            sb.AppendLine(" public int Delete(int id)");
            sb.AppendLine("{");
            sb.AppendLine(" string sql = \"delete from " + tableName + " where Id=@Id\";");
            sb.AppendLine("return SQLHelper.ExecuteNonQuery(sql,new SqlParameter(\"Id\",id));");
            sb.AppendLine("}");

            //Update方法
            sb.AppendLine("public int Update("+tableName+" model)");
            sb.AppendLine("{");
            string[] uParams1=(from col in cols select col+"=@"+col).ToArray();
         
            sb.AppendLine(" string sql = \"update "+tableName+" set "+String.Join(",",uParams1)+" where Id=@Id\";");

            string[] uParams2 = (from col in cols select  "new SqlParameter(\"" + col + "\",model." + col + ")").ToArray();
            sb.AppendLine(" return SQLHelper.ExecuteNonQuery(sql, " + String.Join(",", uParams2) + " ,new SqlParameter(\"Id\",model.Id));");
            sb.AppendLine("}");
          
            //GetId方法
            sb.AppendLine(" public "+tableName+" Get(int id)");
            sb.AppendLine("{");
            sb.AppendLine("string sql=\"select * from "+tableName+" where Id=@Id\";");
            sb.AppendLine(" DataTable dt=SQLHelper.ExecuteDataTable(sql,new SqlParameter(\"Id\",id));");
            sb.AppendLine("if (dt.Rows.Count<=0)");
            sb.AppendLine("{");
            sb.AppendLine(" return null;");
            sb.AppendLine("}");
            sb.AppendLine(" else if (dt.Rows.Count==1)");
            sb.AppendLine("{");
            sb.AppendLine(""+tableName+" model1 = new "+tableName+"();");
            foreach (DataRow row in dt.Rows)
            {
                string col = Convert.ToString(row["COLUMN_NAME"]);
                string dataType = Convert.ToString(row["data_TYPe"]);
                sb.AppendLine("model1." + col + " = Convert." + Get(GetType(dataType).ToString()) + "(dt.Rows[0][\"" + col + "\"]);");
                
            }
            sb.AppendLine("return model1;");
            sb.AppendLine("}");
            sb.AppendLine("else");
            sb.AppendLine("{");
            sb.AppendLine(" throw new Exception(\"数据库中有两条及以上重复数据\");");
            sb.AppendLine("}");
            sb.AppendLine("}");

            //IEnumerable()方法
            sb.AppendLine(" public IEnumerable<"+tableName+"> GetAll()");
            sb.AppendLine("{");
            sb.AppendLine(" string sql = \"select * from "+tableName+"\";");
            sb.AppendLine("DataTable dt = SQLHelper.ExecuteDataTable(sql);");
            sb.AppendLine(" List<"+tableName+"> list = new List<"+tableName+">();");
            sb.AppendLine(" foreach (DataRow row in dt.Rows)");
            sb.AppendLine("{");
            sb.AppendLine("" + tableName + " model = new " + tableName + "();");
            foreach (DataRow row in dt.Rows)
            {
                string col = Convert.ToString(row["COLUMN_NAME"]);
                string dataType = Convert.ToString(row["data_TYPE"]);
                sb.AppendLine("model." + col + " = Convert." + Get(GetType(dataType).ToString()) + "(row[\"" + col + "\"]);");
                
            }
            sb.AppendLine(" list.Add(model);");
            sb.AppendLine("}");
            sb.AppendLine("return list;");
            sb.AppendLine("}");
            sb.AppendLine("}");
            sb.AppendLine("}");
            File.WriteAllText(@"d:\"+tableName+"DAL.cs",sb.ToString());

            
        }
        /// <summary>
 /// 数据库类型转换为C#类型
 /// </summary>
 /// <param name="dataType"></param>
 /// <returns></returns>
        private static Type GetType(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "nvarchar":
                case "varchar":
                case "nchar":
                case "char":
                    return typeof(string);
                case "int" :
                    return typeof(int);
                case "bigint":
                    return typeof(long);
                case "bit":
                    return typeof(bool);
                case "datetime":
                    return typeof(DateTime);
                default:
                    return typeof(object);
            }
        
        }

        private static string Get(string dataType)
        {
         
            switch (dataType.ToLower())
            {
                case "system.string":
                    return "ToString";
                case "system.int32":
                    return "ToInt32";
                case "system.int64":
                    return "ToInt64";
                case "system.datetime":
                    return "ToDateTime";
                case "system.boolean":
                    return "ToBoolean";
             
                default:
                    throw new Exception("找不到匹配的数据类型");
                    
            }
        }
        private static void CreatModel(string tableName, DataTable dt)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using System.Linq;");
            sb.AppendLine("using System.Text;");
            sb.AppendLine("namespace 三层架构Demo.Model");
            sb.AppendLine("{");
            sb.AppendLine("");
            sb.AppendLine("class " + tableName);
            sb.AppendLine("{");

            foreach (DataRow row in dt.Rows)
            {
                string dataType = Convert.ToString(row["DATA_TYPE"]);
                
                string columnName = Convert.ToString(row["COLUMN_NAME"]);

                sb.AppendLine("public " + GetType(dataType) + " " + columnName + " { get;set;}");
            }
            sb.AppendLine("}");
            sb.AppendLine("}");
            File.WriteAllText(@"d:\" + tableName + ".cs", sb.ToString());
            //MessageBox.Show(sb.ToString());
            
        }

        private static void CreatBLL(string tableName, DataTable dt)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using System.Linq;");
            sb.AppendLine("using System.Text;");
            sb.AppendLine("using 三层架构Demo.Model;");
            sb.AppendLine("using 三层架构Demo.DAL;");
            sb.AppendLine("using System.Data.SqlClient;");
            sb.AppendLine("using System.Data;");
            sb.AppendLine("namespace 三层架构Demo.BLL");
            sb.AppendLine("{");
            sb.AppendLine("class " + tableName+"BLL");
            sb.AppendLine("{");
            sb.AppendLine("public int Addnew("+tableName+" model)");
            sb.AppendLine("{");
            sb.AppendLine(" return new "+tableName+"DAL().Addnew(model);");
            sb.AppendLine("}");
            sb.AppendLine(" public int Delete(int id)");
            sb.AppendLine("{");
            sb.AppendLine(" return new "+tableName+"DAL().Delete(id);");
            sb.AppendLine("}");
            sb.AppendLine(" public int Update("+tableName+" model)");
            sb.AppendLine("{");
            sb.AppendLine(" return new " + tableName + "DAL().Update(model);");
            sb.AppendLine("}");
            sb.AppendLine(" public "+tableName+" Get(int id)");
            sb.AppendLine("{");
            sb.AppendLine(" return new "+tableName+"DAL().Get(id);");
            sb.AppendLine("}");
            sb.AppendLine(" public IEnumerable<"+tableName+"> GetAll()");
            sb.AppendLine("{");
            sb.AppendLine(" return new "+tableName+"DAL().GetAll();");
            sb.AppendLine("}");
            sb.AppendLine("}");
            sb.AppendLine("}");
            File.WriteAllText(@"d:\" + tableName + "BLL.cs", sb.ToString());
        }
    }
}

总结:
忽略了很多限制因素,所以代码生成器功能不是很完善。随着要考虑的条件增多,代码生成器越加复杂。但万变不离其中,只要有耐心,继续AppendLine()添加新语句,相信功能会愈加完善。“
工欲善其事必先利其器“,程序员不仅会用代码生成器,而且知道其原理才是优秀的程序员。切勿”知其然而不知其所以然“。

[转载]Android自动开关机实现

mikel阅读(960)

[转载]Android自动开关机实现 – Melanie Deng – 博客园.

关于Android自动关机,网上有很多应用程序和例子。 相对于自动开机来说,自动关机可以在应用层通过设置alarm来实现。而自动开机,网上的介绍就比较少了,因为它需要底层rtc时钟的支持。前段时间根据客户需求实现了自动开关机。在这里分享一下。

1. 简介

我的实现是在设置程序里面增加一个接口,让用户设置自动开关机,这个自动开关机的设置可以参照闹钟的设置。关于自动关机,考虑到关机的时候,用户可能正有一些重要的操作,那么应该给用户一个机会去取消当前的关机。

1)一个BroadcastReceiver, 接收如下信息:

  a) 自定义的ACTION_REQUEST_POWER_OFF:设置auto power off时,通过AlarmManager设置的一个RTC_WAKEUP时钟。当到设置的关机时间时,之前设置到AlarmManager的这个 action会被广播。我们实现的这个BroadcastReceiver接收到这个消息后,就要开始power off流程

  b) 自定义的ACTION_REQUEST_POWER_ON:设置auto power on时,通过AlarmManager设置的一个RTC_WAKEUP时钟。我们知道power on的应该设置一个rtc的alarm,那么这个RTC_WAKEUP的alarm是做 什么的呢?其实当用户设置自动关机的时候,我设置了2个时钟,一个是RTC时钟,用于关机状态下开机;还有一个就是这个RTC_WAKEUP时钟。之所以 设置这个时钟,其实是这样的,比如说你设置了周一到周五每天7点半自动开机,而周四早上你7点就打开了手机,这样到7点半的时候,之前设置的时钟就过期 了,如果不重新设置的话,周五早上是不会自动开机的。所以这个时候,之前设置的RTC_WAKEUP就接收到了这样的信息,在重新设置下次自动开机的时 钟。

  c) BOOT_COMPLETE和TIMEZONE changed, Time set等时间相关的action:当系统开机完成或时间、时区发生改变时,都需要重新设置alarm。

2)一个处理power off 的Service,当BroadcastReceiver接收到ACTION_REQUEST_POWER_OFF,我们给用户一个机会去取消当前的自动关机。这个Service的作用就是启动一个无背景的页面,给用户提示。同时播放之前用户设置的提示音或振动。

3)一个Activity:显示一个dialog提示用户要自动关机,并用一个计时器倒计时。当用户确认关机,或者计时器到时间的时候,就关机。否则取消当前关机,并重设下次自动关机alarm。


2. 自动关机的实现。自动关机的实现比较简单,这里主要说一下怎么设置alarm,和实现关机:

1) 设置自动关机的alarm:

    AlarmManager am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);

        Intent intent = new Intent(
                "com.android.settings.action.REQUEST_POWER_OFF");

        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_CANCEL_CURRENT);
        am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);

2)自动关机掉的是./frameworks/base/services/java/com/Android/server/ShutdownActivity.java:

        Intent newIntent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(newIntent);

Intent.ACTION_REQUEST_SHUTDOWN是Intent里面一个隐藏的action。

3. 自动开机的实现。一直在做上层应用和framework,对于底层不是很熟悉。正好有同事之前做过关机闹铃,所以把他之前的实现稍加改动就可以了。在系统 power off的状态下自动开机,我们需要设置一个rtc时钟,当用户设置自动开机时,由AlarmManagerService将时钟设置下去。这学要底层的支 持。这里的实现是定义一个我们自己的rtc alarm type:

1) 首先要在头文件里面定义:

  a) kernel/include/linux/Android_alarm.h

#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
#define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)

/* we define ANDROID_RTC_ALARM_SET for auto power off */
#define ANDROID_RTC_ALARM_SET               _IOW('a', 7, int)

#define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))

  b) bionic/libc/kernel/common/linux/android_alarm.h

#define ANDROID_RTC_ALARM_SET _IOW('a', 7, int)

2) 定义完成之后,还需要实现:在kernel/drivers/rtc/alarm-dev.c文件的alarm_ioctl方法里面,增加一个case,实现设置alarm

    case ANDROID_RTC_ALARM_SET:
        {
            unsigned int rtc_alarm_time;
            struct rtc_time rtc_now;
            if (copy_from_user(&rtc_alarm_time, (void __user *)arg,
                sizeof(rtc_alarm_time))) {
                rv = -EFAULT;
                goto err1;
            }
            if (pmic_rtc_get_time(&rtc_now) < 0) {
                rtc_now.sec = 0;
                if (pmic_rtc_start(&rtc_now) < 0) {
                    printk("get and set rtc info failed\n");
                    break;
                }
            }
            pmic_rtc_disable_alarm(PM_RTC_ALARM_1);
            rtc_now.sec += rtc_alarm_time;
            pmic_rtc_enable_alarm(PM_RTC_ALARM_1, &rtc_now);
            break;
        }

当然不要忘记增加一个include:

#include <mach/pmic.h>

3)在frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp里面增加一个方法去设置时钟:

static void android_server_AlarmManagerService_updateRtcAlarm(JNIEnv* env, jobject obj, jint fd, jint seconds)
{
#if HAVE_ANDROID_OS
    int result = ioctl(fd, ANDROID_RTC_ALARM_SET, &seconds);
    LOGE("set rtc alarm to %d later: %s\n", seconds, strerror(errno));
    if (result < 0)
    {
        LOGE("Unable to set rtc alarm to %d later: %s\n", seconds, strerror(errno));
    }
#endif
}

还有就是不要忘记定义一下接口:

{"updateRtcAlarm", "(II)V", (void*)android_server_AlarmManagerService_updateRtcAlarm},

4) 在frameworks/base/services/java/com/android/server/AlarmManagerService.java里面定义native的设置alarm的方法,然后调用就可以实现将自动关机的alarm设置下去了:

定义:private native void updateRtcAlarm(int fd, int seconds);

调用:

    public void setRepeating(int type, long triggerAtTime, long interval, 
            PendingIntent operation) {
        if (operation == null) {
            Slog.w(TAG, "set/setRepeating ignored because there is no intent");
            return;
        }
        synchronized (mLock) {
            Alarm alarm = new Alarm();
            alarm.type = type;
            alarm.when = triggerAtTime;
            alarm.repeatInterval = interval;
            alarm.operation = operation;

            // Remove this alarm if already scheduled.
            removeLocked(operation);

            if (localLOGV) Slog.v(TAG, "set: " + alarm);

            int index = addAlarmLocked(alarm);
            if (index == 0) {
                setLocked(alarm);
            }

            // Start to setup auto power on alarm
            if ((alarm.type == AlarmManager.ELAPSED_REALTIME_WAKEUP) && 
                                alarm.operation.getTargetPackage().equals("com.android.settings")) {
                updateRtcAlarm(mDescriptor, (int)((alarm.when - System.currentTimeMillis()) / 1000));
            }
            // End to setup auto power on alarm
        }
    }

5)在应用层设置自动开机

        AlarmManager am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(
                "com.android.settings.action.REQUEST_POWER_ON");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                intent, PendingIntent.FLAG_CANCEL_CURRENT);
        am = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pendingIntent);


4. 总结

1) 自动开机原理比较简单,但是需要底层的支持,所以对于做应用或者framework层的技术人员来说,实现起来稍微比较麻烦。
2) 在设置自动开关机的时候,需要考虑的情况很多,比如是否设置时间/时区的改变,手机当前是开机还是关机状态等。

[转载]开源一个小程序 HttpDownloader

mikel阅读(808)

[转载]开源一个小程序 HttpDownloader – 张志敏 – 博客园.

最近对在线版 CutTheRope 非常感兴趣, 总想下载下来好好研究一下, 于是便写了一个 Http 下载的小工具, 根据 Url 列表进行多线程下载, 然后根据 Url 的相对路径进行保存, 使用起来感觉不错, 现在分享给大家。

HttpDownloader 使用起来非常简单, 只要简单的输入 Url 列表, 选择本地保存目录, 然后就可以开始批量下载了, 程序运行截图如下:

程序运行截图

点击下载按钮之后开始下载, 等进度条走到尽头就下载完了, 最后下载好的文件如下图所示:

image

怎么采集到 Url 呢? 这样的工具有很多, 我用的是 HttpWatch , 只要将 HttpWatch 记录到的 Url 保存到 csv 文件, 用 Excel 打开, 稍微处理一下就得到 url 列表了。

最后说明一下, 这个小程序需要的运行时是 WPF 4.0 , 相信大家都已经安装了 VS2010 了吧, 这个应该不是问题啦。

程序下载地址是 http://files.cnblogs.com/beginor/HttpDownloader.zip

源码下载地址是 https://github.com/beginor/practice/tree/master/src/wpf

整理好的 CutTheRope 下载 http://115.com/file/c2m60rk3

[转载]SQL Server 2000数据库移植到SQL Server 2008R2数据库服务器中碰到的”3145错误”及解决办法

mikel阅读(888)

[转载]SQL Server 2000数据库移植到SQL Server 2008R2数据库服务器中碰到的”3145错误”及解决办法 – Ritchie(乞戈) – 博客园.

辛苦忙碌了一个星期终于安装配置好了TFS服务器,给每个团队成员分配了账户和邮箱。不过,老机器中的部分数据需要备份到新机器中,其中在移植一个使用DVBBS架设的论坛的时候,出了点问题,记录如下,以备查找,也希望能帮助到其他人。

由 于论坛已经运行了一段时间,包括公司注册用户、相关讨论共享等重要资料,需要将其移植到新安装TFS服务器的机器上,并对外公开访问权限。旧的机器上安装 的是SQL Server 2000,在将论坛数据库备份之后,在SQL Server 2008R2的数据库上还原的过程中,出现了如下的3145错误:

备份集中的数据库备份与现有的 ‘xxx’ 数据库不同。

一直以为SQL Server数据库是向前后兼容的,怎么可能存在这样的问题呢?不过检查一番之后,确定两台数据库服务器都没有问题,且论坛的备份在原数据库服务器上可以正常还原。没办法,改之,把在SQL Server 2008R2上新建的数据库更改为 SQL Server 2000格式的,再尝试还原,仍然是同样的错误。在网上找了下,说到的办法,尝试了不少,其中有一篇是“备份集中的数据库备份与现有的数据库不同 SQL 2005 ERROR:3145 解决办法 ”,提供了如下命令方法:

1.新建一个与现有数据库重名的数据库

2.在查询窗口运行如下语句:

use master
restore database AdventureWorks from disk = ‘E:\databasebackup\AdventureWorks.bak’
with replace, MOVE N’AdventureWorks_Data’ TO N’C:\Program Files\Microsoft SQL Server\MSSQL.5\MSSQL\Data\AdventureWorks.mdf’, MOVE N’AdventureWorks_Log’ TO N’C:\Program Files\Microsoft SQL Server\MSSQL.5\MSSQL\Data\AdventureWorks_log.ldf’

从语句上来看,和在图形界面的操作是一样的,但是结果却是语句运行成功,图形界面怎么过不去。

在其他网页上也看到了类似的方法,也有不少成功解决这个错误的,不过,在SQL Server 2008R2服务器上,还是无法正确备份,也没有找到有其它人在SQL Server 2008R2上,用其它方法解决还原备份的问题。

不过,将论坛数据库从旧的SQL Server 2000上分离出来,再附加上SQL Server 2008R2上,成功,数据完整的恢复了!

不清楚为什么在SQL Server 2005上可以,在SQL Server 2008R2却不能恢复备份。不过,好在使用分离和附加的方法,成功将论坛迁移。在此记下,做为参考吧。

[转载]SQLite学习手册(索引和数据分析/清理)

mikel阅读(913)

[转载]SQLite学习手册(索引和数据分析/清理) – Stephen_Liu – 博客园.

一、创建索引:

SQLite中,创建索引的SQL语法和其他大多数关系型数据库基本相同,因为这里也仅仅是给出示例用法:
    sqlite> CREATE TABLE testtable (first_col integer,second_col integer);
    –创建最简单的索引,该索引基于某个表的一个字段。
    sqlite> CREATE INDEX testtable_idx ON testtable(first_col);
    –创建联合索引,该索引基于某个表的多个字段,同时可以指定每个字段的排序规则(升序/降序)。
    sqlite> CREATE INDEX testtable_idx2 ON testtable(first_col ASC,second_col DESC);
    –创建唯一性索引,该索引规则和数据表的唯一性约束的规则相同,即NULL和任何值都不同,包括NULL本身。
    sqlite> CREATE UNIQUE INDEX testtable_idx3 ON testtable(second_col DESC);
    sqlite> .indices testtable
    testtable_idx
    testtable_idx2    
    testtable_idx3
从.indices命令的输出可以看出,三个索引均已成功创建。

二、删除索引:

索引的删除和视图的删除非常相似,含义也是如此,因此这里也只是给出示例:
    sqlite> DROP INDEX testtable_idx;
    –如果删除不存在的索引将会导致操作失败,如果在不确定的情况下又不希望错误被抛出,可以使用”IF EXISTS”从句
    sqlite> DROP INDEX testtable_idx;
    Error: no such index: testtable_idx
    sqlite> DROP INDEX IF EXISTS testtable_idx;

三、重建索引:

重建索引用于删除已经存在的索引,同时基于其原有的规则重建该索引。这里需要说明的是,如果在REINDEX语句后面没有给出数据库名,那么当前连接下 所有Attached数据库中所有索引都会被重建。如果指定了数据库名和表名,那么该表中的所有索引都会被重建,如果只是指定索引名,那么当前数据库的指 定索引被重建。
    –当前连接attached所有数据库中的索引都被重建。
    sqlite> REINDEX;
    –重建当前主数据库中testtable表的所有索引。
    sqlite> REINDEX testtable;
    –重建当前主数据库中名称为testtable_idx2的索引。
    sqlite> REINDEX testtable_idx2;

四、数据分析:

和PostgreSQL非常相似,SQLite中的ANALYZE命令也同样用于分析数据表和索引中的数据,并将统计结果存放于SQLite的内部系统表中,以便于查询优化器可以根据分析后的统计数据选择最优的查询执行路径,从而提高整个查询的效率。见如下示例:
    –如果在ANALYZE命令之后没有指定任何参数,则分析当前连接中所有Attached数据库中的表和索引。
    sqlite> ANALYZE;
    –如果指定数据库作为ANALYZE的参数,那么该数据库下的所有表和索引都将被分析并生成统计数据。
    sqlite> ANALYZE main;
    –如果指定了数据库中的某个表或索引为ANALYZE的参数,那么该表和其所有关联的索引都将被分析。
    sqlite> ANALYZE main.testtable;
    sqlite> ANALYZE main.testtable_idx2;

五、数据清理:

和PostgreSQL中的VACUUM命令相比,他们的功能以及实现方式非常相似,不同的是PostgreSQL提供了更细的粒度,而SQLite只 能将该命令作用于数据库,无法再精确到数据库中指定的数据表或者索引,然而这一点恰恰是PostgreSQL可以做到的。
当某个数据库中的一个或多个数据表存在大量的插入、更新和删除等操作时,将会有大量的磁盘空间被已删除的数据所占用,在没有执行VACUUM命令之 前,SQLite并没有将它们归还于操作系统。由于该类数据表中的数据存储非常分散,因此在查询时,无法得到更好的批量IO读取效果,从而影响了查询效 率。
在SQLite中,仅支持清理当前连接中的主数据库,而不能清理其它Attached数据库。VACUUM命令在完成数据清理时采用了和 PostgreSQL相同的策略,即创建一个和当前数据库文件相同大小的新数据库文件,之后再将该数据库文件中的数据有组织的导入到新文件中,其中已经删 除的数据块将不会被导入,在完成导入后,收缩新数据库文件的尺寸到适当的大小。该命令的执行非常简单,如:
sqlite> VACUUM;

[转载]open-flash-chart + PHP + jQuery实例

mikel阅读(1049)

[转载]open-flash-chart + PHP + jQuery实例 – 轩脉刃 – 博客园.

这个文章说一下open-flash-chartPHPJQuery的结合使用的例子

 

需求UI

 

解释下这个需求:

1 下方是一个flash的图表

2 上方有复选框,日活跃和周活跃用户

3 右方的一周和一月的span标签选择是显示x坐标轴的时间范围,有昨天起前一周和前一月两个选择

4 点击左边的复选框和右边的span标签都会更新flash统计表

 

实现步骤:

1 下载open-flash-chart 2.0

这里使用的版本是:

open-flash-chart-2-Lug-Wyrm-Charmer

 

2 将里面的js(json.js, swfobject.js)php-ofc-libriary文件夹和open-flash-chart.swf

放到服务器目录上

 

3  html的模板使用:

<div id=”c” class=”p010″ style=”height:280px;”>

                <form name=”user_data” action=”#”
data-type
=”platform_static”
data-stat-url
=”ajax/aj_static_user_data.php”
data-stat-aid
=”{{$appinfo.aid}}”>
<div class=”dataHd clearfix”>
<div class=”l”>
<input class=”slc reload_chart”
name
=”dayuv”
type
=”checkbox”
checked
=”checked”
value
=”1″
/>
<label class=”sl”>日活跃</label>&nbsp;&nbsp;&nbsp;
<input
class=”slc reload_chart”
name
=”weekuv”
type
=”checkbox”
checked
=”checked”
value
=”2″
/>
<label class=”cgr”>周活跃</label>
</div>
<div class=”r”>
<input type=”hidden” name=”range” value=”week”>
<div class=”mr5″>
<span class=”week_month cp” name=”week”>一周</span>
<span class=”cd”></span>
<span class=”week_month cp sl” name=”month”>一月</span>
</div>
</div>
</div>
</form>
<div id=”user_data” name=”flash_chart”></div>
</div>

 

这个模板说明:

1 使用了form表单,这样能增加js的可复用性,form表单作为查询提交,from后面的同级目录下的div作为flash展示的div,所以必须标注id值

这里将form的name和div的id设置的相同

2 form表单的属性

data-type=”platform_static”  //说明只要有这个属性的form,提交就是进行flash更新

data-stat-url=”ajax/aj_static_user_data.php”  //这个标注是为了标注上更新flash所提交的ajax的地址

 

 

4  JavaScript(JQuery):

reloadLine的函数,这个函数的作用是提交表单,更新flash

function reLoadLine(id)
{
var form_id = $j(“form[name='” + id + “‘]”);
var aj_url = form_id.attr(‘data-stat-url’) + “?aid=”+ form_id.attr(‘data-stat-aid’) +”&”+ form_id.serialize();
aj_url = encodeURIComponent(aj_url);
swfobject.embedSWF(
“open-flash-chart.swf?r=”+Math.random() * 100000, id,
“750”, “250”, “9.0.0”, “expressInstall.swf”,
{“data-file”: aj_url}, {‘wmode’:”transparent”}
);

    }

几个说明:

1 使用id作为参数是表示值需要将id传入,就可以将对应的flash进行更新

2 aj_url = encodeURIComponent(aj_url);  //作为swf传入的url必须进行urlencode

3 “open-flash-chart.swf?r=”+Math.random() * 100000  //这个后面的随机数必须加上,否则有的浏览器会由于缓存的问题而无法更新

4 {“data-file”: aj_url}  //说明取数据去aj_url中取,后面会说明这个ajax如何写

5 {‘wmode’:”transparent”} // 这个是表示将flash置于最底层

6 页面已经导入了json.js, swfobject.js. 并将jQuery的$ 换为 $j

 

5 JavaScript绑定事件:

$j(‘.reload_chart’).change(function(event){
var target = event.currentTarget;
var form_id = $j(target).parents(‘form[data-type=platform_static]’).attr(‘name’);
reLoadLine(form_id);
});

$j(‘.week_month’).click(function(event){
event.preventDefault();
var target = event.currentTarget;

if($j(target).hasClass(‘sl’))
{
//change the page show
        $j(target).removeClass(‘sl’);
$j(target).nextAll(‘.week_month’).addClass(‘sl’);
$j(target).prevAll(‘.week_month’).addClass(‘sl’);

//change hidden input
        var rangeValue = $j(target).attr(‘name’);
$j(target).parent().prevAll(“input[name=range]”).val(rangeValue);

var form_id = $j(target).parents(‘form[data-type=platform_static]’).attr(‘name’);
reLoadLine(form_id);
}
});

这个熟悉jQuery的同学一看就明白了

就是有一点,再强调一下,这边的$j相当于jQuery中的$

 

6 aj_static_user_data.php

View Code 

这个php有点长,是根据open-flash-chart 2.0的教程改写的

注意点:

1 必须导入正确的ofc-library/open-flash-chart.php

2 最后的json使用toPrettyString生成

 

至此,完成open-flash-chart 和 jquery 和 php 的结合使用

 

碰到的问题 

在写的过程中,经常会碰到错误:

Open Flash Chart IO ERROR Loading test data

或者

“can not find y-32.txt”等类型的错误

最可能的情况是:ajax返回的数据错误,这个可以用fidder调试出来,特别查看里面值为null的字段

 

另外抱怨一下:open-flash-chart的文档真的错误很多,哎~毕竟是免费的

 

参考资料:

http://teethgrinder.co.uk/open-flash-chart-2/

http://pullmonkey.com/2008/7/23/open-flash-chart-ii-plugin-for-ruby-on-rails-ofc2/

 

作者:yjf512(轩脉刃)

出处:http://www.cnblogs.com/yjf512/

本文版权归yjf512和cnBlog共有,欢迎转载,但未经作者同意必须保留此段声明

[转载]如何优化一个网站使之提高访问速度

mikel阅读(1190)

[转载]如何优化一个网站使之提高访问速度–更新20120216 – 前方2012 – 博客园.

最近公司开始考核企业站下所有站点,首先从itpub开始进行。为此,开始学习关于如何 优化一个网站使之提高访问速度这方面的知识。得知page speed 是个不错的工具,就下载下来了。介绍下这个工具吧,Page Speed 是开源 Firefox/Firebug 插件。网站管理员和网络开发人员可以使用 Page Speed 来评估他们网页的性能,并获得有关如何改进性能的建议。对网站的网络服务器配置和前端代码执行若干测试。这些测试基于一组已知可增强网页性能的最佳实践。在网页上运行 Page Speed 的网站管理员会获得一组针对各网页的分数,以及有关如何改善网页性能的有用建议。它会使你的网站更快速,减少带宽成本。

下面以我们的itpub站点为列简要说下:

1 首先你得安装这个插件,具体怎么按,略过;

2 安装后,按F12出现下图

 

3 点击上图花圈的 出现下图:

 

这个82/100是你这个站按照page speed的考核获得分数

自己决定还是不错的。

黄色的表示 警告 可以进一步优化的

绿色的表示做的不错

红色的表示做的不行需要优化了

(itpub没有红色的 这点做的还是不错的)

 

4 看下“启用keep-alive” 关于keep-alive 我会在我的另外一篇博文中着重写下。待续

 

说明it168.com这台主机需要启用keep-alive,可是这是其他项目组的主机,我这边无权修改。所以,在这说下,以后非自己管辖的主机,就直接pass了不管。

5 说下下面的压缩JavaScript

pagespeed给你的建议是 进行压缩以下的2个js。你点击后面的op…它会给你生成个压缩后的js。然后你可以替换原先的js即可。这地方只说明怎么做。当然了JQuery也有min版的压缩后的js。

6 上CDN

其实做了这些 还有个更重要的方面,如果你的公司没钱的话,可以按照上面的来做。如果公司有钱,可以加动态CDN

明后天开始给ITPUB上动态CDN,同时对图片 附件 分离出来用单独的域名。目前首页首屏时间为3.156s

 

希望在上完CDN后网速会得到很大的提高!!!

 

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

这里说下关于性能优化技巧方面一些认识,也是网上传的沸沸扬扬的“军规”:

1 启用gzip。

gzip压缩是一种开发的压缩算法,目前的主流浏览器(Firefox, Safari, Chrome, IE4及以上)与主流服务器(Apache, Lighttpd, Nginx)均对其有很好的支持。gzip压缩是通过HTTP 1.1协议中的Content-Encoding : gzip来进行标记说明,其可以明显减少文本文件的大小,从而节省带宽和加载时间。我做过的一个实验,发现启用gzip后,JQuery 1.2.6 minify版本的大小从54.4k减少到16k,减少了70%。gzip适用的情况包括:

HTML\CSS\JavaScript文 件,gzip算法对于文本文件的效率比较高,而jpg/gif/png/pdf等二进制文件本身已经进行了一次压缩,再使用gzip的成效已经不明显了。 而且gzip压缩需要消耗服务器的资源,而解压缩需要消耗浏览器的资源,对于比较大的二进制文件具有非常高的性能消耗;
尽量使用一种大小写方式,要么全部大写,要么全部小写。学过数据结构和算法的同学一定知道压缩其本身就是对冗余信息熵进行压缩,如何数据原素的类型种类太多,其信息冗余度会降低,从而压缩率降低;
过小的文件(通常小于150个字节)不宜进行gzip压缩,因为gzip会在文件头加入相关信息,对于小文件反而会增加文件的长度;

(以上文字摘自http://www.yakecan.com/archives/3 我表示认同)

那么怎么看你的服务器是否开启了呢?

以我这边的一台服务器为例说明下,我的web服务器是nginx的,就以nginx说下:

打开nginx的配置文件,你会看到相关的gzip的设置,如果没有的话,请你们公司的运维同事设置启用即可

 

types 是使用哪些类型的文件使用到gzip。

 

你可以用站长工具查看你的站点是否使用gzip了,如使用http://tool.chinaz.com/Gzips/可以查看

以我的一个站点为例,

 

大家可以看到这个结果就知道了。

 2 最小化JS和图片

你可以用一个压缩工具压缩即可。对 于JavaScript文件本身具有非常大的优化空间。所谓JavaScript压缩,就是通过一些工具将函数、变量名进行优化(其实就是尽可能缩短变量 名长度),消除多余字符(比如空格、换行符、注释等),最终得到的代码可以在分析和执行上得到性能提升。压缩后得到的代码对于机器而言是可读的,对于人来 说就不行了,因为文件内容已经面目全非。所以压缩一般用于生产期的代码,不能使用于开发期。

3 JavaScript最小化

比如JQuery.form.js,最小化后减少11.9kb,减少54.8%的空间。点击minified version,在新窗口中可以看到Page Speed为你优化好的版本,直接更新到服务器就可以了。

4 启用浏览器缓存

这是经常使用的方法。当请求的资源在浏览器本地得到缓存后,第二次请求这些内容就可以从直接缓存中取出,减少了连线的HTTP请求。

5 JavaScript延迟加载

   通常浏览器在解析HTML时遇到JS文件会先下载,解析执行后才会下载后面的内容,期间自然会造成一定的延时。为了提高性能,尽可能将JS文件的位置后 移,如果可能,还可以通过部分代码进行异步加载。另外,对于JS和CSS在必须放置在一起情况,需要报JS放置在CSS之后,这样CSS与JS文件可以同 步下载。

6 文件拼接,就是可以合并的文件,就合并成一个文件

7 减少HTTP请求。这个是同上面的几个一起使用的。

8 只加载head里的部分js。其他的可以放到底部加载。

9 压缩HTML代码。

有个不错的方法就是压缩HTML,压缩html 其实就是:清除换行符,清除制表符,去掉注释标记  。它所起到的作用不可小视。

现提供PHP 压缩HTML函数。请大家不妨试试看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * 压缩html : 清除换行符,清除制表符,去掉注释标记 
 * @param   $string 
 * @return  压缩后的$string
 * */
function compress_html($string) { 
    $string = str_replace("\r\n", '', $string); //清除换行符 
    $string = str_replace("\n", '', $string); //清除换行符 
    $string = str_replace("\t", '', $string); //清除制表符 
    $pattern = array
                    "/> *([^ ]*) *</", //去掉注释标记 
                    "/[\s]+/"
                    "/<!--[^!]*-->/"
                    "/\" /"
                    "/ \"/"
                    "'/\*[^*]*\*/'"
                    ); 
    $replace = array
                    ">\\1<"
                    " "
                    ""
                    "\""
                    "\""
                    ""
                    ); 
    return preg_replace($pattern, $replace, $string); 
}