转帖自:http://wudataoge.blog.163.com/blog/static/80073886200961652022389/

一.WITH AS的含义 
    WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数据的部分。 
特别对于UNION ALL比较有用。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以可以使用WITH AS短语,则只要执行一遍即可。如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。
二.使用方法
先看下面一个嵌套的查询语句:

select * from person.StateProvince where CountryRegionCode in 
         (select CountryRegionCode from person.CountryRegion where Name like 'C%')

    上面的查询语句使用了一个子查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句非常难以阅读和维护。因此,也可以使用表变量的方式来解决这个问题,SQL语句如下:

declare @t table(CountryRegionCode nvarchar(3))
insert into @t(CountryRegionCode)  (select CountryRegionCode from person.CountryRegion where Name like 'C%')

select * from person.StateProvince where CountryRegionCode 
                     in (select * from @t)


    虽然上面的SQL语句要比第一种方式更复杂,但却将子查询放在了表变量@t中,这样做将使SQL语句更容易维护,但又会带来另一个问题,就是性能的损失。由于表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况。为此,在SQL Server 2005中提供了另外一种解决方案,这就是公用表表达式(CTE),使用CTE,可以使SQL语句的可维护性,同时,CTE要比表变量的效率高得多。

    下面是CTE的语法:

[ WITH <common_table_expression> [ ,n ] ]
<common_table_expression>::=
        expression_name [ ( column_name [ ,n ] ) ]
    AS
        ( CTE_query_definition )

    现在使用CTE来解决上面的问题,SQL语句如下:

 

with
cr as
(
    select CountryRegionCode from person.CountryRegion where Name like 'C%'
)

select * from person.StateProvince where CountryRegionCode in (select * from cr)

    其中cr是一个公用表表达式,该表达式在使用上与表变量类似,只是SQL Server 2005在处理公用表表达式的方式上有所不同。

    在使用CTE时应注意如下几点:
1. CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。如下面的SQL语句将无法正常使用CTE:


with
cr as
(
    select CountryRegionCode from person.CountryRegion where Name like 'C%'
)
select * from person.CountryRegion  -- 应将这条SQL语句去掉
-- 使用CTE的SQL语句应紧跟在相关的CTE后面 --
select * from person.StateProvince where CountryRegionCode in (select * from cr)


2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示:

 

with
cte1 as
(
    select * from table1 where name like 'abc%'
),
cte2 as
(
    select * from table2 where id > 20
),
cte3 as
(
    select * from table3 where price < 100
)
select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id

3. 如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了,如下面的SQL语句所示:


--  table1是一个实际存在的表

with
table1 as
(
    select * from persons where age < 30
)
select * from table1  --  使用了名为table1的公共表表达式
select * from table1  --  使用了名为table1的数据表

4. CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。

5. 不能在 CTE_query_definition 中使用以下子句:

(1)COMPUTE 或 COMPUTE BY

(2)ORDER BY(除非指定了 TOP 子句)

(3)INTO

(4)带有查询提示的 OPTION 子句

(5)FOR XML

(6)FOR BROWSE

6. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:

declare @s nvarchar(3)
set @s = 'C%'
;  -- 必须加分号
with
t_tree as
(
    select CountryRegionCode from person.CountryRegion where Name like @s
)
select * from person.StateProvince where CountryRegionCode in (select * from t_tree)

使用with as 完成递归:

With RootNodeCTE(Id,ParentId)   
As   
(   
Select Id,ParentId From Dept Where ParentId =0 
Union All   
Select Dept.Id,Dept.ParentId From RootNodeCTE   
Inner Join Dept  
On RootNodeCTE.Id = Dept.ParentId   
)   
  
Select * From RootNodeCTE  
--生成测试数据  
create table Dept(ID int,ParentID int,msg varchar(20))  
insert into Dept select 1,0,null  
insert into Dept select 2,1,null  
insert into Dept select 3,1,null  
insert into Dept select 4,2,null  
insert into Dept select 5,3,null  
insert into Dept select 6,5,null  
insert into Dept select 7,6,null  
--go
--DROP TABLE Dept

  

posted @ 2011-09-08 15:55 李传涛 阅读(42) 评论(2) 编辑

(原创:灰灰虫的家http://hi.baidu.com/grayworm

一、WebService中常用的属性(Attributes)
1. Web Service(Web服务)提供以下三个属性。
Namespace:此属性的值包含 XML Web Service的默认命名空间。XML命名空间提供了一种在XML文档中创建名称的方法,该名称可由统一资源标识符(URI)标识。如果不指定命名空间,则使用默认命名空间 http://tempuri.org/
Name:此属性的值包含XML Web Service的名称。在默认情况下,该值是实现XML Web Service的类的名称。
Description:此属性的值包含描述性消息,此消息将在XML Web Service的说明文件(例如服务说明和服务帮助页)生成后显示给XML Web Service的潜在用户。

示例代码如下:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
//......
}
运行结果:


《图1》

2. WebMethod(Web服务方法)有以下4个常用属性。

Description:是对Web Service方法的描述信息。就像Web Service方法的功能注释,可以让调用者看见的注释。

示例代码如下:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod(Description = "显示所有人员的信息")]
public InfoData[] GetInfos(out string emsg)
{
//...
}
}
运行结果:


《图2》

EnableSession:指示Web Service是否启动Session标志,主要通过Cookie完成,默认为false。
默认情况下WebService的方法中不能使用Session,如果使用会产生异常。
示例代码如下:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod(Description = "显示所有人员的信息")]
public InfoData[] GetInfos(out string emsg)
{
Session["test"] = DateTime.Now.ToString();
return new InfoDA().Select().ToArray();
}
}
运行结果:


《图3》

要在WebService中使用Session需要把上面的代码进行如下修改:

[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod(Description = "显示所有人员的信息", EnableSession = true)]
public InfoData[] GetInfos(out string emsg)
{
Session["test"] = DateTime.Now.ToString();
return new InfoDA().Select().ToArray();
}
}

TransactionOption:指示Web Service方法的事务支持。
要在WebService中使用事务时,不需要编写很多的代码,只需要在WebMethod属性中加上启用事务的声明即可
示例代码如下:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod(TransactionOption= TransactionOption.RequiresNew)]
public void AddInfo(InfoData data)
{
new InfoDA().Insert(data);
new InfoDA().Insert(data);
}
}
在上面的代码中向数据库中插入了两次数据,在第二次插入数据时会产生主键重复的异常。如果查看数据库时我们会发现第一次Insert也没有插入成功。这就是因为我们在该方法上加入了事务的功能。

CacheDuration:设置响应应在缓存中保留的秒数。这样Web Service就不需要重复执行多遍,可以提高访问效率,而CacheDuration就是指定缓存时间的属性。
示例代码如下:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod( EnableSession=true, CacheDuration=10)]
public string GetCNDateTime()
{
return DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒ms毫秒");
}
}
上面的服务方法缓存了10秒钟。
在我们运行该服务,手动调用方法的时候会发现好像缓存并没有起作用,每次调用的显示的时间总会变化。其实该缓存的效果在直接运行的时候并不会起作用,当我们编写客户端代码调用该服务的时候会发现缓存的确是起作用了。
客户端代码如下:
public static void Main(string[] args)
{
Services.MyServiceSoapClient client = new Client.Services.MyServiceSoapClient();
string str = client.GetCNDateTime();
Console.WriteLine(str);
}
在运行该客户端代码的时候,在10秒钟之内的两次运行显示的时间是不变的。

二、WebService的调用。
我们可以使用ASP.NET Web程序、WinForm程序、控制台程序和javascript来调用WebService。
ASP.NET、WinForm、控制台调用WebService方法基本一样也很简单,主要是添加Web引用,调用代理类来实现的,这里我们不再举例。
下面我们主要看一下如何使用JavaScript来调用WebService

WebService代码如下:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod]
public string GetCNDateTime()
{
return DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒ms毫秒");
}
}

客户端JS调用代码如下:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<div id="dd"></div>
</div>
</form>
</body>
</html>
<script language="javascript">
function showTime() {
//下面我们使用XMLDOM对象对WebService访问,因为WebService是以XML方式传输数据的,所以我们可以使用XMLDOM对象来解析WebService返回的数据
var obj = new ActiveXObject("Microsoft.XMLDOM");
//设定读取方式是同步方式
obj.async = false;
//指定XMLDOM对象要加载的WebService方法返回的XML数据
//如果使用开发服务器的运行WebService的话,那需要选运行起这个WebService。
obj.load("
http://localhost/TestWS/Service.asmx/GetCNDateTime");
//取得返回的XML数据中的文本
var res = obj.documentElement.text;
dd.innerHTML = res;
}
window.setInterval(showTime, 1000);
</script>

这样运行并不成功会产生下面的问题:


《图4》

这是因为WebService并不接收JavaScript提交的方式。要完善这个问题我们需要在WebService的web.config配置文件中加入下面的配置
<system.web>
<webServices>
<protocols>
<add name="HttpPost"/>
<add name="HttpGet"/>
</protocols>
</webServices>
.........
</system.web>


《图5》

三、实现异步调用Web Service
普通调用Web Service的方法,在Web Service执行期间客户端会一直等待服务执行完毕才能响应。从而造成客户端UI线程的阻塞假死现象。这时候,异步调用就显得很有用,它可以让客户端在调用Web Service时,不至于阻塞客户端的UI线程导致假死,还可以在调用Web Service的同时做些其他的处理。
第一种方法,是通过利用Backgroundworker对象实现。
BackgroundWorker 类允许你在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面(UI)似乎处于停止响应状态。如果你需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
class Program
{
public static void Main(string[] args)
{
//实现异步调用
BackgroundWorker bgw = new BackgroundWorker();
//DoWork事件是在BackgroundWorker对象调用RunWorkerAsync()方法后要触发的事件
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
//RunWorkerCompleted事件是DoWork指向的方法执行完成的回调事件
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
//启运异步调用
bgw.RunWorkerAsync();
Debug.WriteLine("Main Function is Over....");
Console.ReadLine();
}

static void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Debug.WriteLine("Work is over...");
}

static void bgw_DoWork(object sender, DoWorkEventArgs e)
{
Debug.WriteLine("Work is Processing...");
}
}

打印的结果应当是:
Main Function is Over....
Work is Processing...
Work is over...

其中的Main函数线程和bgw_DoWork线程同时运行的。

第二种方法,是调用Web Service的WebMethod中的Async方法实现。
当添加完Web Service的引用以后,会在本地生成代理类,其中,会有一个和原Web Service方法名字相同而后缀是Async的方法。
在.NET FrameWork3.5中并不会自动产生这种异步方法。需要我们来生成一下。
在“Web引用”上右击,选择“配置服务引用...”


《图6》
在服务引用设置窗口中把“生成异步操作”复选框选中点击确定。


《图7》
在客户端编写代码的时候,我们会看到代理类中的每个方法都多了个异步操作的方法


《图8》
客户端完整代码如下:
public static void Main(string[] args)
{
Services.MyServiceSoapClient client = new Client.Services.MyServiceSoapClient();
client.GetCNDateTimeCompleted += new EventHandler<Client.Services.GetCNDateTimeCompletedEventArgs>(client_GetCNDateTimeCompleted);
client.GetCNDateTimeAsync();
Debug.WriteLine("Doing other things");
Console.ReadLine();
}
运行结果如图所示:


《图9》

四、保证Web Service的安全
要以安全的方式访问Web服务方法,可以考虑以下安全措施:
是谁调用?——SoapHeader身份认证。
来自哪里?——访问IP认证。
加密传输 ——SSL安全访问。
在这里我们主要来讨论前两种措施,至于SSL安全访问需要对操作系统进行配置,这里不再赘述。
(一)SoapHeader身份认证。
1.在Web Service中定义自己的SoapHeader派生类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services.Protocols;

public class MySoapHeader:SoapHeader
{
private string _UserName;

public string UserName
{
get { return _UserName; }
set { _UserName = value; }
}
private string _Password;

public string Password
{
get { return _Password; }
set { _Password = value; }
}
public MySoapHeader() { }
public MySoapHeader(string uid,string pwd)
{
_UserName = uid;
_Password = pwd;
}
public bool IsValid(out string errorMsg)
{
errorMsg = "";
if (_UserName == "admin" && _Password == "123")
{
return true;
}
else
{
errorMsg = "您无权调用该服务";
return false;
}
}
}

2.在Web Service中添加基于SoapHeader验证的Web Service接口方法:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public MySoapHeader SoapHeader = new MySoapHeader();
[SoapHeader("SoapHeader")]
[WebMethod(Description = "显示所有人员的信息")]
public InfoData[] GetInfos(out string emsg)
{
if (!SoapHeader.IsValid(out emsg))
return null;
return new InfoDA().Select().ToArray();
}
}

3.在客户端调用具有SoapHeader的Web Service
Services.MyServiceSoapClient client = new Client.Services.MyServiceSoapClient();
Services.MySoapHeader header = new Client.Services.MySoapHeader();
header.UserName = "admin";
header.Password = "asasas";

e.Result = client.GetInfos(header,out outmsg);
Console.WriteLine(outmsg);

《图10》

(二)访问IP认证。
对来源IP的检查来进行验证,我们只允许指定IP的服务器来访问,保证点对点的安全。
bool ValidateIP(int UserID, out string exceptionInfo)
{
exceptionInfo = "";
string uip = HttpContext.Current.Request.UserHostAddress;
Common dal = new Common();
List<string> ips = dal.GetPermitIp(UserID);//得到该用户ID所允许的IP列表
if (ips == null || ips.Count == 0)
{
exceptionInfo = "调用Web服务的客户端IP未被允许,无法访问!";
return false;
}
if (ips.Contains(uip)) //允许IP列表中包含该IP
{
return true;
}
exceptionInfo = "调用Web服务的客户端IP未被允许,无法访问!";
return false;
}
在具体Web方法里调用该方法检查用户访问者是否是以我们允许的IP进行访问的,以确保安全。
优点:简单,防止非指定客户机器访问。
缺点:IP是可以伪造的;维护IP地址表比较烦琐。且只适合于固定IP访问者的情况。


Web Service开发中需要注意的问题
WebMethod的名字、参数和返回值应该一看就知道这接口大概是干什么用的。
WebMethod参数要尽量简单。只有一个参数的服务接口,往往不能满足业务需求。但过多的参数也提高了出错的几率
WebMethod要提供对参数和返回值的校验
WebMethod返回值应该是简单的语言无关
WebMethod谨慎地抛出异常
对Web Service中的任何异常都应该进行相应的处理。可以简单地归纳为以下两种情况。
第1种情况是返回值是简单类型,比如bool型,就true和false两种情况,不抛出异常怎么办?选择有两种,一是抛出异常,二是改变接口,返回int用1和0对应true和false,用-1对应系统异常。
第2种情况是返回值是复杂对象,可以通过参数out string exceptionInfo来返回异常信息。

WebMethod禁用HTTP POST/GET协议
Web服务绑定到3种协议:HTTP/POST、HTTP/GET和SOAP。HTTP/GET的安全性不如SOAP。
WebMethod避免使用ASP.NET会话状态

原文地址:http://hi.baidu.com/fss199/blog/item/a5012b8ff3e33519b31bbac0.html

posted @ 2011-07-19 17:27 李传涛 阅读(78) 评论(0) 编辑

  先看一下语法结构:

如果是在不同服务器上创建同义词,就需要添加server_name,比如添加远程服务器(192.168.1.5,2800)的TestDB数据库的T_Employee表

SQL代码如下:

CREATE SYNONYM dbo.Test FOR[192.168.1.5,2800].[TestDB].[dbo].T_Employee

但是当你去执行SELECT * from TestSQL文时,会报错,主要是没有添加链接服务器,存储过程具体使用方法参考如下链接:

sp_addlinkedserver    sp_addlinkedsrvlogin

EXEC sys.sp_addlinkedserver '192.168.1.5,2800','','SQLNCLI','192.168.1.5,2800',NULL,'DRIVER={SQL Server};SERVER=TestDB;UID=sa;PWD=as;'  
EXEC sys.sp_addlinkedsrvlogin '192.168.1.5,2800','false',null,'sa','as'

删除链接服务器:

EXEC sp_dropserver   '192.168.1.5,2800', 'droplogins'

第二个参数为droplogins时,会自动删除对应的登录信息

ALTER procedure [sys].[sp_dropserver]
	@server		sysname,			-- server name
	@droplogins	char(10) = NULL		-- drop all related logins?
as
//

posted @ 2011-06-28 17:25 李传涛 阅读(14) 评论(0) 编辑

这是一堂关于UML基础知识的补习课;现在我们做项目时间都太紧了,基本上都没有做过真正的class级别的详细设计,更别提使用UML来实现规范建模了;本篇主要就以前自己一直感觉很迷糊的几种class之间的关系进行整理,让我们在真正用UML进行比如类图设计时能够更加清晰明了;以下就分别介绍这几种关系:

继承

指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系;在Java中此类关系通过关键字extends明确标识,在设计时一般没有争议性;

实现

指的是一个class类实现interface接口(可以是多个)的功能;实现是类与接口之间最常见的关系;在Java中此类关系通过关键字implements明确标识,在设计时一般没有争议性;

依赖

可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、、临时性的、非常弱的,但是B类的变化会影响到A;比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖;表现在代码层面,为类B作为参数被类A在某个method方法中使用;

关联

他体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比如我和我的朋友;这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的、关联可以是单向、双向的;表现在代码层面,为被关联类B以类属性的形式出现在关联类A中,也可能是关联类A引用了一个类型为被关联类B的全局变量;

聚合

聚合是关联关系的一种特例,他体现的是整体与部分、拥有的关系,即has-a的关系,此时整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享;比如计算机与CPU、公司与员工的关系等;表现在代码层面,和关联关系是一致的,只能从语义级别来区分;

组合

组合也是关联关系的一种特例,他体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合;他同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束;比如你和你的大脑;表现在代码层面,和关联关系是一致的,只能从语义级别来区分;

对于继承、实现这两种关系没多少疑问,他们体现的是一种类与类、或者类与接口间的纵向关系;其他的四者关系则体现的是类与类、或者类与接口间的引用、横向关系,是比较难区分的,有很多事物间的关系要想准备定位是很难的,前面也提到,这几种关系都是语义级别的,所以从代码层面并不能完全区分各种关系;但总的来说,后几种关系所表现的强弱程度依次为:组合>聚合>关联>依赖;

原文地址:http://blog.csdn.net/sfdev/archive/2009/02/18/3906243.aspx

posted @ 2011-06-18 23:23 李传涛 阅读(46) 评论(0) 编辑
什么是设计原则? 

设计原则是基本的工具,应用这些规则可以使你的代码更加灵活、更容易维护,更容易扩展。

基本原则

oop
  • 封装变化Encapsulate what varies.
  • 面向接口编程而非实现 Code to an interface rather than to an implementation.
  • 优先使用组合而非继承 Favor Composition Over Inheritance

SRP: The single responsibility principle 单一职责

系统中的每一个对象都应该只有一个单独的职责,而所有对象所关注的就是自身职责的完成。

Every object in your system should have a single responsibility ,and all the object s services should  be focused on carrying out that single responsibility .

 

  1. 每一个职责都是一个设计的变因,需求变化的时候,需求变化反映为类职责的变化。当你系统里面的对象都只有一个变化的原因的时候,你就已经很好的遵循了SRP原则。
  2. 如果一个类承担的职责过多,就等于把这些职责耦合在了一起。一个职责的变化就可能削弱或者抑制这个类其它职责的能力。这种设计会导致脆弱的设计。当变化发生的时候,设计会遭到意想不到的破坏。
  3. SRP 让这个系统更容易管理维护,因为不是所有的问题都搅在一起。
  4. 内聚Cohesion 其实是SRP原则的另外一个名字.你写了高内聚的软件其实就是说你很好的应用了SRP原则。
  5. 怎么判断一个职责是不是一个对象的呢?你试着让这个对象自己来完成这个职责,比如:“书自己阅读内容”,阅读的职责显然不是书自己的。
  6. 仅当变化发生时,变化的轴线才具有实际的意义,如果没有征兆,那么应用SRP或者任何其它的原则都是不明智的。

DRY : Don't repeat yourself Principle

通过抽取公共部分放置在一个地方避免代码重复.

Avoid duplicate code by abstracting out things that are common and placing those thing in a single location .

 

  1. DRY 很简单,但却是确保我们代码容易维护和复用的关键。
  2. 你尽力避免重复代码候实际上在做一件什么事情呢?是在确保每一个需求和功能在你的系统中只实现一次,否则就存在浪费!系统用例不存在交集,所以我们的代码更不应该重复,从这个角度看DRY可就不只是在说代码了。
  3. DRY 关注的是系统内的信息和行为都放在一个单一的,明显的位置。就像你可以猜到正则表达式在.net中的位置一样,因为合理所以可以猜到。
  4. DRY 原则:如何对系统职能进行良好的分割!职责清晰的界限一定程度上保证了代码的单一性。

OCP : Open-Close Principle开闭原则

类应该对修改关闭,对扩展打开;

Classes should be open for extension ,and closed  for modification .

 

  1. OCP 关注的是灵活性,改动是通过增加代码进行的,而不是改动现有的代码;
  2. OCP的应用限定在可能会发生的变化上,通过创建抽象来隔离以后发生的同类变化
  3. OCP原则传递出来这样一个思想:一旦你写出来了可以工作的代码,就要努力保证这段代码一直可以工作。这可以说是一个底线。稍微提高一点要求,一旦我们的代码质量到了一个水平,我们要尽最大努力保证代码质量不回退。这样的要求使我们面对一个问题的时候不会使用凑活的方法来解决,或者说是放任自流的方式来解决一个问题;比如代码添加了无数对特定数据的处理,特化的代码越来越多,代码意图开始含混不清,开始退化。
  4. OCP 背后的机制:封装和抽象;封闭是建立在抽象基础上的,使用抽象获得显示的封闭;继承是OCP最简单的例子。除了子类化和方法重载我们还有一些更优雅的方法来实现比如组合;

怎样在不改变源代码(关闭修改)的情况下更改它的行为呢?答案就是抽象,OCP背后的机制就是抽象和多态

  1. 没有一个可以适应所有情况的贴切的模型!一定会有变化,不可能完全封闭.对程序中的每一个部分都肆意的抽象不是一个好主意,正确的做法是开发人员仅仅对频繁变化的部分做出抽象。拒绝不成熟的抽象和抽象本身一样重要。
  2. OCPOOD很多说法的核心,如果这个原则有效应用,我们就可以获更强的可维护性 可重用 灵活性 健壮性 LSPOCP成为可能的主要原则之一

LSP: The Liskov substitution principle

子类必须能够替换基类。

Subtypes must be substitutable  for their base types.

 

  1. LSP关注的是怎样良好的使用继承.
  2. 必须要清楚是使用一个Method还是要扩展它,但是绝对不是改变它。
  3. LSP清晰的指出,OODIS-A关系是就行为方式而言,行为方式是可以进行合理假设的,是客户程序所依赖的。
  4. LSP让我们得出一个重要的结论:一个模型如果孤立的看,并不具有真正意义的有效性。模型的有效性只能通过它的客户程序来表现。必须根据设计的使用者做出的合理假设来审视它。而假设是难以预测的,直到设计臭味出现的时候才处理它们。
  5. 对于LSP的违反也潜在的违反了OCP

DIP:依赖倒置原则

高层模块不应该依赖于底层模块 二者都应该依赖于抽象

抽象不应该依赖于细节 细节应该依赖于抽象

  1. 什么是高层模块?高层模块包含了应用程序中重要的策略选择和业务模型。这些高层模块使其所在的应用程序区别于其它。
  2. 如果高层模块依赖于底层模块,那么在不同的上下文中重用高层模块就会变得十分困难。然而,如果高层模块独立于底层模块,那么高层模块就可以非常容易的被重用。该原则就是框架设计的核心原则。
  3. 这里的倒置不仅仅是依赖关系的倒置也是接口所有权的倒置。应用了DIP我们会发现往往是客户拥有抽象的接口,而服务者从这些抽象接口派生。
  4. 这就是著名的Hollywood原则:"Don't call us we'll call you."底层模块实现了在高层模块声明并被高层模块调用的接口。
  5. 通过倒置我们创建了更灵活 更持久更容易改变的结构
  6. DIP的简单的启发规则:依赖于抽象;这是一个简单的陈述,该规则建议不应该依赖于具体的类,也就是说程序汇总所有的依赖都应该种植于抽象类或者接口。
  7. 如果一个类很稳定,那么依赖于它不会造成伤害。然而我们自己的具体类大多是不稳定的,通过把他们隐藏在抽象接口后面可以隔离不稳定性。
  8. 依赖倒置可以应用于任何存在一个类向另一个类发送消息的地方
  9. 依赖倒置原则是实现许多面向对象技术多宣称的好处的基本底层机制,是面向对象的标志所在。

ISP:接口隔离原则

不应该强迫客户程序依赖它们不需要的使用的方法。

  1. 接口不是高内聚的,一个接口可以分成N组方法,那么这个接口就需要使用ISP处理一下。
  2. 接口的划分是由使用它的客户程序决定的,客户程序是分离的接口也应该是分离的。
  3. 一个接口中包含太多行为时候,导致它们的客户程序之间产生不正常的依赖关系,我们要做的就是分离接口,实现解耦。
  4. 应用了ISP之后,客户程序看到的是多个内聚的接口。
原文地址:http://www.cnblogs.com/me-sa/archive/2008/03/31/dp.html
posted @ 2011-06-18 23:19 李传涛 阅读(10) 评论(0) 编辑
JS script

function ConfirmMe()
{
   return confirm("Do you want to proceed?");
}


ASPX

<asp:TextBox id="txtName" runat="server"/>
<asp:Button id="btnSubmit" OnClientClick="return ConfirmMe()" Text="Submit" runat="server"/>


Well, that is pretty straightforward. BUT, it goes weird when you have a validator control (eg. RequiredFieldValidator) that is used to validate the "txtName" textbox server control. For instance,


<asp:TextBox id="txtName" runat="server"/>

<asp:RequiredFieldValidator id="rq1" ControlToValidate="txtName" ErrorMessage="Name cannot be blank" Display="Dynamic" runat="server"/>

<asp:Button id="btnSubmit" OnClientClick="return ConfirmMe()" Text="Submit" runat="server"/>


Whenever you press the button with no textbox value, the client-side confirmation dialog will be invoked first before the validator message is able to show up. This isn't what we expected it to behave. I tried several ways to overcome this problem, including using CLIENT CALLBACK, disabling the CauseValidation, but it failed. Finally, I was able to find a solution by adding JUST ONE line in the JS script.

function ConfirmMe()
{
   if(Page_ClientValidate())
      return confirm('Do you want to proceed?');

   return false;
}
posted @ 2011-06-18 23:13 李传涛 阅读(24) 评论(0) 编辑

在new SqlBulkCopy对象的时候,设置一下SqlBulkCopyOptions选项即可,按位或运算

SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.CheckConstraints
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(GlobalString.ConnectionString,
          SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers))
 {
   //...........
}

posted @ 2011-05-26 17:03 李传涛 阅读(128) 评论(0) 编辑
摘要: 面向对象的三个基本特征(讲解)面向对象的三个基本特征是:封装、继承、多态。封装封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。继承面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”。被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritanc阅读全文
posted @ 2011-05-25 14:48 李传涛 阅读(36) 评论(0) 编辑
摘要: 修改此问题 需要在 创建视图语句中加上 with SCHEMABINDINGcreate View myView with SCHEMABINDING as select id,code from dbo.mytable注意,表的表达式必须使用两段式 dbo.mytable 否则会报 "名称必须由两部分构成,并且对象不能引用自身。"同时显示字段也不能用×表示,必须指明具体的列阅读全文
posted @ 2011-05-23 17:45 李传涛 阅读(266) 评论(1) 编辑
摘要: 1、可能是IP地址配置不对。解决方法如下: 打开 \Microsoft SQL Server 2005\配置工具\下的SQL Server Configuration Manager,选择mssqlserver协议, 然后双击右边窗口的TCP/IP,在弹出窗口中检查IP配置。 一般来讲,默认的IP2是:127.0.0.1,如果第一个IP地址的端口1433端口ping不通的话,服务无法启动。您可以将127.0.0.1放在IP1上,那么不管IP2的端口是否能ping通,服务都能够正常启动。您也可以将IP1设置为当前机器的IP地址,并保证该IP地址的端口能够ping通,方法如下: telnet lo阅读全文
posted @ 2011-05-12 17:26 李传涛 阅读(318) 评论(0) 编辑