一个很有趣的插件,能显示博客评论者的相关信息,并以图标的方式显示出来,包括评论者IP所在的国家、浏览器、操作系统,这种统计还是比较有意思,也相当直观,看图吧:
安装过程也很方便,后台直接启用,然后小小设置一下,就OK了。
一个很有趣的插件,能显示博客评论者的相关信息,并以图标的方式显示出来,包括评论者IP所在的国家、浏览器、操作系统,这种统计还是比较有意思,也相当直观,看图吧:
安装过程也很方便,后台直接启用,然后小小设置一下,就OK了。
为了试试在手机上twitter,据说英文版的UCWEB可以正常访问,于是去了UC的官方,发现英文版的UCWEB,竟然还不是7.0版本的,而是6.3的,看来版本更新不够快啊,选定自己的手机型号,下载下来装上,发现果然还可以twitter……只是习惯了7.0的界面,6.X的版本看起来有点丑陋了。另外,发现个小问题,英文版里面访问在线书签,显示乱码,希望高手指点下,同步网络书签貌似有点问题,以文件导出、导入的方式应该可以解决书签问题,不过我还没试过。
悄声说一下,英文版UC下载地址:http://www.uc.cn/English/download.shtml 嘘……
由于身边的几个同事都是单反爱好者,每天交流的话题也如此,耳濡目染,终于,偶义无反顾的中毒了……决定最近入手单反,加入DSLR的行列,无奈自己对单反的了解还比较浅显,所以决定先入一本入门教程,在互动网发现了这本书,评价还不错,而且送1DVD和镜头手册,原价80多,打折下来69.42,还包邮费,相当超值了。从今天开始好好学习,天天向上。
一直以来,我的blog用的wp-t-wap插件实现博客的手机浏览,感觉还不错,插件启用时,会自动生成手机浏览所需的页面文件。无意中发现博客好友久酷同学在使用MobilePress,自己去down了一个,试用了一下,果然不错,比起wp-t-wap更轻量级,插件支持多种主题以及自定义主题。而且插件启用后,能够自动识别访问的客户端,如果发现是手机等移动设备,就自动启用MobilePress的主题,相当方便。推荐还没有安装的同学使用。插件的安装和设置也很简单,就不在此累述了……
MobilePress 插件
下载地址: http://wordpress.org/extend/plugins/mobilepress/
周末之时,即是系统上线之日,周五下班后,和同事一起驱车去西河大吃兔子,一大份外加一中份,很是过瘾,也为晚上熬夜补充营养。接着回到办公室dota两把,午夜12点后开始系统调试、上线到生产环境,一直到第二天早上快7点,收拾东西闪人,发现车子没油了,郁闷,去对面的加油站加油,告知不能刷卡,只加了100块,更郁闷。随后一路狂飙回家,看了看表,7点半,天已经微微亮了,竟然发觉自己没有一点困意,看来偶通宵的功夫还真不是盖的。回到家,发现乖女已经醒了,洗脸洗脚,睡了……
Linq to Sql中默认采用的模式就是延迟执行,所谓延迟执行,其实就是在获取对象本身时,并不会获取和其关联的其他对象,只有在访问其关联对象的时候,程序才会去加载关联对象的数据到内存中。这样的好处是程序不会在初次访问的时候,就加载大批量的数据,而是以一种延迟加载的方式进行处理,相对而言,对于系统和网络的性能开支会减小很多。对于一个默认的Linq to Sql查询,延迟加载就是其默认的设置,不过,在某些情况下,延迟加载并非完全“智能”,不但没有实现其本意,反而增大了网络流量和性能开支。下面我们以SQL Server中的演示数据库NorthWind来试验一下:
LinqTestDataContext ctx = new LinqTestDataContext();
ctx.Log = Console.Out;
var result = ctx.Orders.Where(p => p.OrderID == 10251);
foreach (var t in result)
{
Console.WriteLine("OrderID:"
+ t.OrderID
+ "-"
+ "OrderDate:"
+ t.OrderDate.Value.ToString("yyyy-MM-dd"));
}
通过Linq to sql查询所有OrderID为10251的订单信息,并输出订单编号和订单日期。通过显示Linq的日志输出,我们可以看到后台生成的SQL语句如下:
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[OrderID] = @p0
输出的SQL看来还比较正常。下面我们再来改一下我们的程序:
foreach (var t in result)
{
Console.WriteLine("OrderID:" + t.OrderID
+ "-OrderDate:"
+ t.OrderDate.Value.ToString("yyyy-MM-dd")
+"-CustomerName:"
+ t.Customer.ContactName);
foreach(var m in t.Order_Details)
Console.WriteLine("ProductID:"
+ m.ProductID
+ "-Price:"
+ m.UnitPrice
+ "-Amount:"
+ m.Quantity);
}
出了输出订单相关信息外,还输出其关联对象:客户姓名、订单中的产品编号、单价、数量
再来看看输出的SQL语句:
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[OrderID] = @p0
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactT
itle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Coun
try], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] = @p0
SELECT [t0].[OrderID], [t0].[ProductID], [t0].[UnitPrice], [t0].[Quantity], [t0]
.[Discount]
FROM [dbo].[Order Details] AS [t0]
WHERE [t0].[OrderID] = @p0
我们可以看到,对于我们修改后的代码,程序向数据库请求了三条SQL语句,当然,这还不是最坏的情况,但是我们在这里的确看到延迟加载似乎“变了味道”,不但没有节省开支,反而增大了网络浏览。怎样才能改善这样的情况呢?
其实我们知道,有很多扩展方法会导致延迟加载失效,而开始立即执行。当我们在调用诸如:ToList、ToDictionary、ToLookup或者ToArray之类的扩展方法之后,程序会将最终的结果存放到某个临时的变量集合中,并让所有的数据一次性的加载完成。
另外,还有一种方式,通过设置DataContext的DeferredLoadingEnabled属性为false,显示的关闭默认的延迟加载方式。
LinqTestDataContext ctx = new LinqTestDataContext();
ctx.DeferredLoadingEnabled = false;
这些方式虽然比较方便,但是还是有一定的局限性。例如,简单的使用ToList只能解决一些简单的查询问题,而对于复杂的查询需求,ToList还是不能解决延迟取得子对象所引发的多次查询问题。并且,在大量数据被加载到内存中的时候,对内存的需求也是很大的。不过,幸好Linq to sql给我们提供了另外一套不错的方法。
Linq to Sql提供DataLoadOptions,用以立即加载关联的对象数据,其中包含两种方法:
LoadWith方法,用于立即加载与主对象相关联的数据
AssociateWith方法,用于对关联对象的数据进行筛选,并加载
有了DataLoadOptions,我们就可以用如下的方式优化我们的查询中需要加载的对象:
LinqTestDataContext ctx = new LinqTestDataContext();
ctx.Log = Console.Out;
DataLoadOptions dl = new DataLoadOptions();
dl.LoadWith<order>(p => p.Customer);
dl.LoadWith<order>(p => p.Order_Details);
ctx.LoadOptions = dl;
var result = ctx.Orders.Where(p => p.OrderID == 10251).ToList();
foreach (var t in result)
{
Console.WriteLine("OrderID:" +
t.OrderID
+ "-OrderDate:"
+ t.OrderDate.Value.ToString("yyyy-MM-dd")
+"-CustomerName:"
+ t.Customer.ContactName);
foreach(var m in t.Order_Details)
Console.WriteLine("ProductID:"
+ m.ProductID
+ "-Price:"
+ m.UnitPrice
+ "-Amount:"
+ m.Quantity);
}
对于我们开发者而言,需要注意的是,对于同一个DataContext实例,DataLoadOptions只能设定一次,并且一旦设定,就无法更改。
接下来,运行程序,看看优化后,程序向数据库服务器请求的的SQL:
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry], [t3].[OrderID] AS [OrderID2], [t3].[ProductID], [t3]
.[UnitPrice], [t3].[Quantity], [t3].[Discount], (
SELECT COUNT(*)
FROM [dbo].[Order Details] AS [t4]
WHERE [t4].[OrderID] = [t0].[OrderID]
) AS [value], [t2].[test], [t2].[CustomerID] AS [CustomerID2], [t2].[Company
Name], [t2].[ContactName], [t2].[ContactTitle], [t2].[Address], [t2].[City], [t2
].[Region], [t2].[PostalCode], [t2].[Country], [t2].[Phone], [t2].[Fax]
FROM [dbo].[Orders] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName
], [t1].[ContactTitle], [t1].[Address], [t1].[City], [t1].[Region], [t1].[Postal
Code], [t1].[Country], [t1].[Phone], [t1].[Fax]
FROM [dbo].[Customers] AS [t1]
) AS [t2] ON [t2].[CustomerID] = [t0].[CustomerID]
LEFT OUTER JOIN [dbo].[Order Details] AS [t3] ON [t3].[OrderID] = [t0].[OrderID]
WHERE [t0].[OrderID] = @p0
ORDER BY [t0].[OrderID], [t2].[CustomerID], [t3].[ProductID]
可以看出,之前的分三次向数据库提交sql的情况,现在被程序优化为一条带LEFT JOIN的关联查询,而获取关联数据。三次SQL请求,被优化为一次,从而减少了数据库和网络流量开支,由此看来DataLoadOptions的好处不言而喻。
延迟加载与立即加载,并无孰优孰劣之区别,在某些情况下,需要我们根据自己的需求和实际情况来选择来进行选择。
淘宝最近为了推广淘江湖,推出免费送玩偶的活动,只要你接到好友送的玩偶,就能领取名额,然后再推荐给你的几个朋友,你就能收到好友送的玩偶实物。今天收到了Ven同学送的“阳光男”,在此感谢。玩偶戴个帽子,还有滑板,而且都是可拆卸的,呵呵,很有意思!
Quartz.NET是一套开源的作业调度框架,是最初由Java平台的企业级开源作业调度框架 Quartz 移植到.NET平台的。在sourceforge上,Quartz.NET的主页有这样的介绍: Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems. (Quartz.NET是能应用在小到轻量级的应用程序,大到重量级的企业级系统中的全功能的开源任务调度系统)并且,值得令人信服的是,Quartz.NET已经在生产环境中得以用,并得到了良好的反馈。
回想一下,在小到普通的应用程序,大到企业级项目中,我们常常会遇到需要定时轮询和调度的场景,简单点的需求是每隔固定的秒数或者分钟、小时进行轮询,复杂点的是每周的某个时刻,或者每月,或者每年才执行一次,又或者更复杂的情景,某些天需要执行,某些天不执行。用Windows自带的计划任务,能够实现简单的逻辑,如果要用程序实现这样的逻辑,想必也很复杂了。其实,用Quartz能很好的应付这些情况。
Quartz.NET的核心模块分为几个部分,Scheduler、Job、JobDetail、Trigger
Scheduler:实现调度的主体,负责调度任务的开始、结束,Scheduler中包含已注册的JobDetail和Trigger,并且,当Trigger中的条件得以触发时,Scheduler负责执行和Trigger相关联的Job,实现任务的调度。 Job:需要被调度的任务,Job必须实现IJob接口的Execute方法,而Execute方法的内容,其实也就是我们需要根据不同的需求自己实现的业务逻辑。 JobDetail:包含对Job的具体描述,包括Job的名称、所属的Group名称、以及Job的Type描述,用以Quartz.NET通过反射实现对Job的调用。 Trigger:触发器,描述调度的触发条件和时机。
Quartz.NET之所以没把Job和Trigger设计在一起,而是采用一种松耦合的方式,把Job和Trigger独立为两个不同的对象,原因是因为在Quartz.NET中,Job和Trigger可以建立一种一对多的关系,也就是可以对一个调度任务绑定多个Trigger,另外的好处是当某个Job的Trigger过期的时候,可以直接为Job绑定新的Trigger而不用重新定义和这个Trigger相关联的Job。
最初见到Quartz.NET,还是0.6的版本,一直躺在偶的硬盘里面,直到最近项目中遇到很多需要定时轮询处理的情况,突然想到了Quartz.NET,打开它在sourceforge的大本营,才发现Quartz.NET已经更新到1.0.1版本了。
Quartz.NET为我们提供了简洁的API,通过简单的例子,我们就可以很快上手和使用
在Quartz.NET中,所有的Job都必须实现IJob接口:
namespace Quartz
{
public interface IJob
{
void Execute(JobExecutionContext context);
}
}
JobExecutionContext 包含运行时的一些上下文信息,还可以用来传递参数
编写我们自己的Job,实现IJob接口:
using Quartz;
namespace ExampleJob
{
public class TestJob : IJob
{
public void Execute(JobExecutionContext context)
{
Console.WriteLine("Job executed!");
}
}
}
然后就可以通过Scheduler来调度任务了
// 创建SchedulerFactory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// 获取Scheduler实例
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// 创建JobDetail
JobDetail jobDetail = new JobDetail("ExampleJob", "MyJobGroup", typeof(ExampleJob));
// 创建Trigger,每分钟触发一次
Trigger trigger = TriggerUtils.MakeMinutelyTrigger();
// 设定trigger的开始时间
trigger.StartTimeUtc = TriggerUtils.GetEvenHourDate(DateTime.UtcNow);
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger);
这样,任务调度框架便会每分钟调度一次我们的Job,在控制台每分钟都能看到一句 ”Job executed!”,是不是很简单呢?
其实Quartz.NET还有很多方便开发人员的特性和高级功能,比如通过配置文件配置Job和Trigger,可以让你的调度程序更加灵活,以应对后续需求的变化,而不需要重新编译程序。另外,还有调度线程池、JobStore、Clustering等很多高级功能,等着我们去发现。
相关资源:
Quartz.NET 主页:http://quartznet.sourceforge.net
在sourceforge的Quartz.NET主页上,有入门教程供初学者查看:http://quartznet.sourceforge.net/tutorial/index.html
另外,博客园的张善友也把教程翻译成了中文的,供E文不好的同学学习和参考,地址:http://www.cnblogs.com/shanyou/archive/2007/08/25/QuartzNETtutorial.html
由于某某原因,现在上网变得越来越不容易了,很多网站都经常莫名其妙的打不开,其中有一部分因素,就是遭到DNS劫持。所以,我一般不会用国内的DNS,因为国内的DNS会在解析域名时,“故意”犯错。比较好的方法就是使用国外的免费DNS,这段时间,一直用OpenDNS,效果还不错,今天Google也向公众发布了免费的DNS服务,ping测试了一下,速度还比较快,所以立马采纳了,呵呵。
至此,推荐给大家比较不错的DNS最佳设置(DNS的ping值,电信、网通可能有稍许差异): Google Public DNS服务:速度不错,家中上网,ping值平均220ms 首选DNS:8.8.8.8 备用DNS:8.8.4.4
补: Ben同学提供的另外一个Google未披露的DNS 4.3.2.1 目前测试来看,速度应该是最快的
Open DNS服务:家中上网,ping值平均在400ms 首选DNS:208.67.222.222 备用DNS:208.67.220.220
另外,还有个不错的DNS:家中上网,ping值平均在500ms左右 4.2.2.2
目前看来,还是Google的DNS访问起来比较快,推荐设置为首选。
本Blog使用的皮肤,名字叫 Minyx 2.0 Lite,三栏样式,用起来还算不错,一直比较喜欢。不过,现在的效果已经是是被我改过后的了,原本的样式可以看这里:http://www.pengpengblog.com/ 右边的两栏和左边的一栏各占50%,并且三栏并不是占满整个屏幕的,这样对于展现代码而言比较窄,所以动手修改了CSS布局,让三栏铺满整个屏幕,并调整了后两栏的宽度和一些边栏的布局,让左边显示文章内容的一栏变得更大。有喜欢的朋友可以下载了试试,也可以根据自己的喜好再修改。
皮肤已经更新,请移步到这里下载:https://xiaozhou.net/aboutsite/wordpress/wordpress_theme_minyx_lite_download_modified_by_timothy-2011-08-03.htm
这两天最热门的东东,无非是Chrome OS了,虽然正式的Chrome OS面世,需要等到一年后左右。但其相关报道已经占据了各大论坛和站点的首页。在Google公布Chromium OS开源项目的同时,国外已经有大牛将源码编译成了操作系统镜像并开放下载。我也迫不及待的Down了一份镜像,放在VirtualBox上玩玩。安装十分简单,建立一个Linux系统的虚拟机,然后加载下载好的操作系统镜像即可。
Google的理念,OS即浏览器,所有体验都在浏览器内进行……![]()
从下载设置,可以看到后台基于Linux的文件系统![]()
因为Chrome OS的桌面即浏览器,这也让网上对于此系统的评价褒贬不一,在我个人看来,这是一次创造性的尝试,用户再也不用担心安装操作系统、驱动程序、应用程序的繁琐,所有的应用都基于网络和浏览器,客户的程序只是一个瘦客户端,后台借助于强大的云计算服务实现对数据的处理和存储,而用户需要关心的只是自己的数据,而这些重要的数据,也会存放在网络中的云端。这种模式在现在看来,或许超前了一些,但对于传统的杀毒软件厂商和应用厂商来说不得不是一次很大的冲击,Chrome OS甚至会影响到未来微软操作系统的地位。嗯嗯,虽然现在的Chrome OS还不太成熟,不过按照Google的思路,将Chrome OS和GAE结合起来,充分运用云计算的优势,这或许将是一个很具有革命性意义的开端……