你的类型应该有一个顺序关系,以便在集合中描述它们如何存储以及排 序。.Net框架为你提供了两个接口来描述对象的顺序关系:IComparable 和 IComparer。IComparable 为你的类定义了自然顺序,而实现IComparer接口的类 可以描述其它可选的顺序。你可以在实现接口时,定义并实现你自己关系操作符 (<,>,<=,>=),用于避免在运行时默认比较关系的低效问题。这 一原则将讨论如何实现顺序关系,以便.Net框架的核心可以通过你定义的接口对 你的类型进行排序。这样用户可以在些操作上得更好的效率。
IComparable接口只有一个方法:CompareTo(),这个方法沿用了传统的C 函数库里的strcmp函数的实现原则:如果当前对象比目标对象小,它的返回值小 于0;如果相等就返回0;如果当前对象比目标对象大,返回值就大于0。 IComparable以System.Object做为参数,因此在使用这个函数时,你须要对运行 时的对象进行检测。每次进行比较时,你必须重新解释参数的类型:
public struct Customer : IComparable
{
private readonly string _name;
public Customer( string name )
{
_name = name;
}
#region IComparable Members
public int CompareTo( object right )
{
if ( ! ( right is Customer ) )
throw new ArgumentException( "Argument not a customer",
"right" );
Customer rightCustomer = ( Customer )right;
return _name.CompareTo( rightCustomer._name );
}
#endregion
}
关于实现比较与IComparable接口的一致性有 很多不太喜欢的地方,首先就是你要检测参数的运行时类型。不正确的代码可以 用任何类型做为参数来调用CompareTo方法。还有,正确的参数还必须进行装箱 与拆箱后才能提供实际的比较。每次比较都要进行这样额外的开销。在对集合进 行排序时,在对象上进行的平均比较次数为N x log(N),而每次都会产生三次装 箱与拆箱。对于一个有1000个点的数组来说,这将会产生大概20000次的装箱与 拆箱操作,平均计算:N x log(n) 有7000次,每次比较有3次装箱与拆箱。因此 ,你必须自己找个可选的比较方法。你无法改变IComparable.CompareTo()的定 义,但这并不意味着你要被迫让你的用户在一个弱类型的实现上也要忍受性能的 损失。你可以重载CompareTo()方法,让它只对Customer 对象操作:
public struct Customer : IComparable
{
private string _name;
public Customer( string name )
{
_name = name;
}
#region IComparable Members
// IComparable.CompareTo()
// This is not type safe. The runtime type
// of the right parameter must be checked.
int IComparable.CompareTo( object right )
{
if ( ! ( right is Customer ) )
throw new ArgumentException( "Argument not a customer",
"right" );
Customer rightCustomer = ( Customer ) right;
return CompareTo( rightCustomer );
}
// type-safe CompareTo.
// Right is a customer, or derived from Customer.
public int CompareTo( Customer right )
{
return _name.CompareTo( right._name );
}
#endregion
}
现在,IComparable.CompareTo()就是一个隐 式的接口实现,它只能通过IComparable 接口的引用才能调用。你的用户则只能 使用一个类型安全的调用,而且不安全的比较是不可能访问的。下面这样无意的 错误就不能通过编译了:
Customer c1;
Employee e1;
if ( c1.CompareTo( e1 ) > 0 )
Console.WriteLine( "Customer one is greater" );
1.单点登录,是一个用得很多,也是大家比较常见的登录方式了。我在这里写这篇文章的目的,是因为我的这个单点登录里,用了简单的设计模式。供大家参考。
2.这篇文章的附件代码,是完整的单点登录代码。您可以直接下载,嵌入您的系统即可直接使用。这是基于前些文章,部分网友提出的要提供代码下载。所以,我采纳了这个建议,非常感谢各位朋友。
配置:
在web.config中,需要在<system.web>节点中,添加如下配置:
其中:machineKey的生成,网上有代码,请自行去google或baidu。关于authentication mode="Forms"的验证方式,请查阅msdn。
在Global.asax全局文件中,加入如下代码:
///<summary> /// 发送身份请求时触发 ///</summary> ///<param name="sender"></param> ///<param name="e"></param> ///<author>马志远(Marc)</author> protected void Application_PostAuthenticateRequest(object sender, EventArgs e) { HttpContext ctx = ((HttpApplication)sender).Context; HttpRequest req = ctx.Request; HttpResponse resp = ctx.Response; if (!UrlAuthorizationModule.CheckUrlAccessForPrincipal(req.AppRelativeCurrentExecutionFilePath, ctx.User, req.RequestType)) { HttpContext.Current.Response.Redirect(String.Format("{0}?ReturnUrl={1}", FormsAuthentication.LoginUrl, req.Url.AbsoluteUri)); } }
文件目录结构:

用法:
1.登录时调用的方法在Passport.cs文件中。调用的代码如下:
通过上面的代码调用,那么用户即可以登录成功了。
2.登录成功后,要取得用户的cookie数据,比如用户名、昵称等。这些方法写在了User.cs中。

调用代码为:
CCNF.Tool.Authentication.User.GetInstance().AdministratorId等。
3.退出系统的代码在SignOut.cs的代码中。
使用上述代码,即可退出系统。
知识点:
其中Passport.cs文件用到了单例模式。单例模式代码如下:
///<summary> /// 构造函数 ///</summary> ///<author>马志远(Marc)</author> private Passport() {
}
static Passport() { }
public static Passport GetInstance() { return instance; }
http://www.cnblogs.com/mazhiyuan/archive/2012/05/16/2503484.html
代码附件下载:
主要内容
1、数据库编程方式的进化
2、NH的系统架构
一、数据库编程方式的进化
在开始介绍NH的系统架构之前,先谈谈我所经历的.net项目组进行数据库编程的方式的变化:
过去:主要是调用存储过程,对于比较简单的数据库操作也可直接编写简单的sql语句。
现在:由于存储过程难以维护,所以建议尽量采取执行sql语句的方式进行数据库操作。同时,为了让大家更加容易的执行sql语句,还总结出了DAAB之类的数据库操作辅助包。
下一步:随着系统的不断增大,之前大量采用sql实现业务逻辑的设计和编码的做法会加大我们项目的维护的难度和成本。而且采取上述方式进行数据库开发的效率非常低,开发人员往往花费大量时间在和数据库打交道,更谈不上thinking in OO。数据库编程转向O/R mapping。
二、NH的系统架构
在继续阅读之前,如果你想先体验一下NH的便利和优雅,可以参考一下我之前发的NHibernate学习手记(1) - 对象的简单CRUD操作。
1、术语解释
1)持久化(persistent)和持久化对象(persitent object):在程序运行时创建的对象,并要求保存到数据库、文件等存储介质中。如订单、人员信息等。
2、NH的持久层功能示意

Application即任何需要持久化服务(即数据存储)的应用程序。NH的持久化功能是以服务形式提供的,实现应用程序代码和数据库操作之间的解偶。当然,为了能够使用NH,我们必须要进行一些配置工作。
3、NH系统架构简图

上图传达了NH进行持久化的简单思想。在应用程序(Application)中创建的临时对象(Transient objects),开始是保存在内存中的;接着应用程序和NH进行对话(Session,事先需要先由SessionFactory创建Session),告知NH需要进行的持久化请求;NH根据配置文件把持久化操作转化为相应的数据库操作,调用相应的ADO.Net API执行数据库操作。
4、NH系统架构全景图
下图揭示了NH更多的技术细节,我将在后续的文章中,继续介绍。

英文原文:Three things you should never put in your database
我已经在很多演讲里说过,改进你的系统的最好的方法是先避免做“蠢事”。我并不是说你或你开发的东西“蠢”,只是有些决定很容易被人们忽略掉其暗含的牵连,认识不到这样做对系统维护尤其是系统升级带来多大的麻烦。作为一个顾问,像这样的事情我到处都能见到,我还从来没有见过做出这样的决定的人有过好的结果的。
图片,文件,二进制数据
既然数据库支持 BLOB 类型的数据,把文件塞进 BLOB 字段里一定没有错了!?错,不是这样的!别的先不提,在很多数据库语言里,处理大字段都不是很容易。
把文件存放在数据库里有很多问题:
- 对数据库的读/写的速度永远都赶不上文件系统处理的速度
- 数据库备份变的巨大,越来越耗时间
- 对文件的访问需要穿越你的应用层和数据库层
这后两个是真正的杀手。把图片缩略图存到数据库里?很好,那你就不能使用 nginx 或其它类型的轻量级服务器来处理它们了。
给自己行个方便吧,在数据库里只简单的存放一个磁盘上你的文件的相对路径,或者使用 S3 或 CDN 之类的服务。
短生命期数据
使用情况统计数据,测量数据,GPS 定位数据,session 数据,任何只是短时间内对你有用,或经常变化的数据。如果你发现自己正在使用定时任务从某个表里删除有效期只有一小时,一天或数周的数据,那说明你没有找对正确的做事情的方法。使用 redis,statsd/graphite, Riak,它们都是干这种事情更合适的工具。这建议也适用于对于收集那些短生命期的数据。
当然,用挖土机在后花园里种土豆也是可行的,但相比起从储物间里拿出一把铲子,你预约一台挖土机、等它赶到你的园子里挖坑,这显然更慢。你要选择合适的工具来处理手头上的事。
日志文件
把日志数据存放到数据库里,表面上看起来似乎不错,而且“将来也许我需要对这些数据进行复杂的查询”,这样的话很得人心。这样做并不是一个特别差的做法,但如果你把日志数据和你的产品数据存放到一个数据库里就非常不好了。
也许你的日志记录做的很保守,每次 web 请求只产生一条日志。对于整个网站的每个事件来说,这仍然会产生大量的数据库插入操作,争夺你用户需要的数据库资源。如果你的日志级别设置为 verbose 或 debug,那等着看你的数据库着火吧。
你应该使用一些比如 Splunk Loggly 或纯文本文件来存放你的日志数据。这样去查看它们也许会不方便,但这样的时候不多,甚至有时候你需要写出一些代码来分析出你想要的答案,但总的来说是值得的。
可是稍等一下,你是那片不一样的雪花,你遇到的问题会如此的不同,所以,如果你把上面提到的三种东西中的某一种放到了数据库里也不会有问题。不,你错了,不,你不特殊。相信我。

