iTimothy

君看一叶舟,出没风波里


  • 首页

  • 分类

  • 归档

  • 项目

  • 关于

Linq to Sql 之延迟加载与立即加载

发表于 2009-12-20 | 分类于 技术控 | | 阅读次数:
字数统计: 1.5k 字 | 阅读时长 ≈ 6 分钟

Linq的延迟加载

Linq to Sql中默认采用的模式就是延迟执行,所谓延迟执行,其实就是在获取对象本身时,并不会获取和其关联的其他对象,只有在访问其关联对象的时候,程序才会去加载关联对象的数据到内存中。这样的好处是程序不会在初次访问的时候,就加载大批量的数据,而是以一种延迟加载的方式进行处理,相对而言,对于系统和网络的性能开支会减小很多。对于一个默认的Linq to Sql查询,延迟加载就是其默认的设置,不过,在某些情况下,延迟加载并非完全“智能”,不但没有实现其本意,反而增大了网络流量和性能开支。下面我们以SQL Server中的演示数据库NorthWind来试验一下:

linq_context

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给我们提供了另外一套不错的方法。

使用DataLoadOptions实现对加载对象的优化

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的好处不言而喻。

###

一点小结

延迟加载与立即加载,并无孰优孰劣之区别,在某些情况下,需要我们根据自己的需求和实际情况来选择来进行选择。

写在女儿半岁之际

发表于 2009-12-07 | 分类于 随笔 | | 阅读次数:
字数统计: 78 字 | 阅读时长 ≈ 1 分钟

还有三天,到2009.12.10,就是女儿半岁的日子了,半年来,小女一天一个样,比起刚生下来的时候,老练了许多。今天来给她打扮打扮,拍照留恋,希望小女健康成长,嘿嘿。真期待她走路,叫老爸的那一天……

OLYMPUS DIGITAL CAMERA         OLYMPUS DIGITAL CAMERA

淘宝玩偶已收到

发表于 2009-12-06 | 分类于 随笔 | | 阅读次数:
字数统计: 104 字 | 阅读时长 ≈ 1 分钟

淘宝最近为了推广淘江湖,推出免费送玩偶的活动,只要你接到好友送的玩偶,就能领取名额,然后再推荐给你的几个朋友,你就能收到好友送的玩偶实物。今天收到了Ven同学送的“阳光男”,在此感谢。玩偶戴个帽子,还有滑板,而且都是可拆卸的,呵呵,很有意思!

IMAG0157IMAG0158

开源的作业调度框架:Quartz.NET

发表于 2009-12-05 | 分类于 技术控 | | 阅读次数:
字数统计: 1.1k 字 | 阅读时长 ≈ 4 分钟

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设置

发表于 2009-12-04 | 分类于 技术控 | | 阅读次数:
字数统计: 311 字 | 阅读时长 ≈ 1 分钟

由于某某原因,现在上网变得越来越不容易了,很多网站都经常莫名其妙的打不开,其中有一部分因素,就是遭到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

发表于 2009-12-02 | 分类于 技术控 | | 阅读次数:
字数统计: 211 字 | 阅读时长 ≈ 1 分钟

本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

发表于 2009-11-23 | 分类于 技术控 | | 阅读次数:
字数统计: 472 字 | 阅读时长 ≈ 1 分钟

这两天最热门的东东,无非是Chrome OS了,虽然正式的Chrome OS面世,需要等到一年后左右。但其相关报道已经占据了各大论坛和站点的首页。在Google公布Chromium OS开源项目的同时,国外已经有大牛将源码编译成了操作系统镜像并开放下载。我也迫不及待的Down了一份镜像,放在VirtualBox上玩玩。安装十分简单,建立一个Linux系统的虚拟机,然后加载下载好的操作系统镜像即可。

首次运行,开机登录,使用Google帐号:
chromeos1

Google的理念,OS即浏览器,所有体验都在浏览器内进行……
chromeos2
从下载设置,可以看到后台基于Linux的文件系统
chromeos3

因为Chrome OS的桌面即浏览器,这也让网上对于此系统的评价褒贬不一,在我个人看来,这是一次创造性的尝试,用户再也不用担心安装操作系统、驱动程序、应用程序的繁琐,所有的应用都基于网络和浏览器,客户的程序只是一个瘦客户端,后台借助于强大的云计算服务实现对数据的处理和存储,而用户需要关心的只是自己的数据,而这些重要的数据,也会存放在网络中的云端。这种模式在现在看来,或许超前了一些,但对于传统的杀毒软件厂商和应用厂商来说不得不是一次很大的冲击,Chrome OS甚至会影响到未来微软操作系统的地位。嗯嗯,虽然现在的Chrome OS还不太成熟,不过按照Google的思路,将Chrome OS和GAE结合起来,充分运用云计算的优势,这或许将是一个很具有革命性意义的开端……

关于Win7 天气插件的问题

发表于 2009-11-17 | 分类于 技术控 | | 阅读次数:
字数统计: 306 字 | 阅读时长 ≈ 1 分钟

最近突然发现自己Win7 gadget中的天气插件罢工了,老是显示Service not available,冥思苦想不得其解,在网上Google了一把,才找到原因,原来在将系统的Region and Language设置为非美国地区或者非英语格式后(比如设置为China),系统中的wlsrvc.dll会在运行时检查你的地区设置,如果检查到设置为India或者China,DLL会返回1506,表示天气服务在你的语言区域不可用。晕死…… 回忆了一下前些日子,为了使用一个软件,不得已改了语言设置,索性把Location改回为United Status, Format改回为English,一切又正常了,天气服务立马可用。嗯,反正我的Windows 7也是英文版的,改回来还是比较方便的方法,网上还有一种比较暴力的方法,就是替换掉那个wlsrvc.dll,有兴趣的同学可以参考下列步骤:

  1. Close and exit Windows Sidebar.

  2. Open Windows Explorer.

  3. Browse to C:\Program Files\Windows Sidebar folder.

  4. Take ownership and grant full permission to you on wlsrvc.dll file.

  5. Rename wlsrvc.dll to wlsrvc.dll.old.

  6. Download the patched wlsrvc.dll (contains inside the wlsrvc.zip).

  7. Copy the patched wlsrvc.dll into the Windows Sidebar folder.

  8. Run the sidebar.exe to restart Windows Sidebar.

[置顶]常用扩展方法收集&整理(置顶-不断更新)

发表于 2009-11-13 | 分类于 技术控 | | 阅读次数:
字数统计: 514 字 | 阅读时长 ≈ 2 分钟

扩展方法,是.NET 3.5中引入的新特性,在《扩展方法使用小结中》,我有具体的介绍。合理的使用扩展方法,能节约不少的代码量,甚至能在开发中给我们带来意想不到的效果,让代码更加的简洁、易懂。其实,网上早就有了不少的大牛写的各种出色的扩展方法,以至于我有了整理一个扩展方法库的想法,把一些实用、优秀的扩展方法收集起来,一来为资源共享,二来也是为了应用在以后的项目代码中,提高开发效率。

阅读全文 »

同时接入多个网络的路由设置

发表于 2009-11-10 | 分类于 技术控 | | 阅读次数:
字数统计: 544 字 | 阅读时长 ≈ 2 分钟

最近在外面调试程序,内网是调试程序必须的,而要上外网,又只有通过无线连接。不过发现这样有个问题,就是在笔记本的无线连上外网的时候,只要插上内网的网线,就发现qq一类的一律掉线,外网连接就不行了,网页也打不开。这样搞的比较麻烦,每次测试完程序,要手动拔掉网线,外网才能上。感觉这样的做法太麻烦了,能否内网和外网同时接入到笔记本,不用每次拔网线呢?于是在网上找了找资料,果然还找到了。其实是因为Windows默认路由设置的问题。Windows每次会默认把对所有IP的访问,指向以太网或者无线网的网关,当同时接入两个、或者多个连接时,这样的默认路由会有问题,需要我们手动修改一下。

需要通过route命令来设置,下面就是个例子,进入CMD(以管理员身份启动):

例如,要想同时使用有线网上内网、无线网上外网,可以这样设置

route delete 0.0.0.0 (删除对所有IP的默认路由设置)

route add 0.0.0.0 mask 0.0.0.0 192.168.1.1 (将对所有IP的路由,指向外网网关IP,外网网关IP假设为192.168.1.1)

route add 10.13.4.0 mask 255.255.255.0 10.122.2.1 (对内网某个网段的访问,指向内网网关地址,内网网关IP假设为10.122.2.1)

其中192.168.1.1为无线网网关,10.122.2.1为有线网网关。这两句话的意思是:对于所有IP地址的访问,都从192.168.1.1走;但是,对于10.13.4开头的地址的访问,从10.122.2.1走。如果希望通过有线上外网,无线上内网的话,以此类推……

这样,再也不用插拔网线这种粗鲁的方式来切换网络了…… Very very happp!

PS: 每个网络接口的IP地址、网关地址,可以通过ipconfig命令获取

手机刷机到WM 6.5-23502

发表于 2009-10-29 | 分类于 技术控 | | 阅读次数:
字数统计: 234 字 | 阅读时长 ≈ 1 分钟

前天逛cnBeta,发现MS发布了新的WM6.5的rom,版本23502,号称在速度方面和界面方面有了一定的改进。于是就在网上搜索看国内有没有发布此ROM,结果果不其然,已经有人放在网上了。呵呵,还等什么,刷就一个字……

总体来说:和以前版本的Windows Mobile相比,开始菜单按钮移到了屏幕下面,样子有点防Windows Vista的味道,对话框的关闭按钮,也是在下方,而且增大了不少,这样更方便用手指按屏幕,而可以减少用笔触的次数。其实感觉手写笔本来就是个鸡肋,用处不大,而仅仅用手指操作也许是未来的趋势。速度方面,还没感觉比上个刷的版本有明显差异……

上图:

VidyaScreen001VidyaScreen003VidyaScreen004

最后,放上此ROM下载地址:

http://hi.baidu.com/vacuity2009/blog/item/a364fac9d4978815bf09e6e9.html

WordPress下的第一篇日志 :-)

发表于 2009-10-25 | 分类于 技术控 | | 阅读次数:
字数统计: 453 字 | 阅读时长 ≈ 1 分钟

自从上次把域名转移到godaddy,就有了把空间也搬家的打算,说干就干,在wpchina.org找到提供wordpress空间服务的国外php主机空间,测试了下速度,还不错,而且价格也不贵,至少比现在的空间便宜一半,于是就下定决心买下了。至于搬家的理由,其实有两点:

1.虽然PJBlog在asp的博客里面,是首选,但是WordPress是一个绝对值得一玩的BLOG,在全世界都有着众多的插件和Fans。

2.空间搬到国外,再也不用bei案了,而且也不怕blog因为某某原因而突然不能访问了。

接着就是一大堆的体力活,将以前的PJBlog的文章导出,再导入到WordPress,由于之前的链接和目录的问题,许多文章的链接都需要更新,而且比较郁闷的是,Linux系统下文件名是要区分大小写的,这也花了不少功夫去更新以前数篇日志的下载链接。忙乎过后,发现皮肤也不太满意,一直比较喜欢自己博客园那个皮肤,在网上搜了搜,名字叫“minyx 2.0 LITE”而且皮肤正好是wordpress下的,很是幸运。换了皮肤,发现宽度也不太满意,于是又把CSS文件一阵狂改,接着改页面内容,加插件。后续的工作还有很多,包括插件的添加,页面的美化,相册的建立,旧日志标签的补充,等等……虽然搞得晕头转向,不过心里着实很高兴。这篇日志也算是WordPress下面的开篇日志吧,小小庆祝一下……

PS:以前的PJBlog作为本Blog的镜像站点,而可以通过http://pj.xiaozhou.net访问。

1…293031…47
Timothy

Timothy

Timothy的技术博客,记录技术以及生活点滴

564 日志
8 分类
1187 标签
RSS
github twitter
Links
  • ZWWoOoOo
  • 花開未央
  • 守望轩
  • 大漠说程序
  • ChengBo
  • BlueAndHack
  • 程序员小辉
  • 子痕的博客
  • WoodenRobot
  • VPS大佬
  • 毕扬博客
  • VPSDad
  • 猫爪导航
  • ss1271的奋斗
  • Kian.Li
  • YoungForest
  • Fred's Blog
  • Jacklandrin
© 2025 Timothy
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4