[SQL]SQL性能优化

mikel阅读(987)

1.查询的模糊匹配
     尽量避免在一个复杂查询里面使用 LIKE '%parm1%'—— 红色标识位置的百分号会导致相关列的索引无法使用,最好不要用.
解决办法:
其实只需要对该脚本略做改进,查询速度便会提高近百倍。改进方法如下:
        a、修改前台程序——把查询条件的供应商名称一栏由原来的文本输入改为下拉列表,用户模糊输入供应商名称时,直接在前台就帮忙定位到具体的供应商,这样在调用后台程序时,这列就可以直接用等于来关联了。
        b、直接修改后台——根据输入条件,先查出符合条件的供应商,并把相关记录保存在一个临时表里头,然后再用临时表去做复杂关联

2.索引问题
        在做性能跟踪分析过程中,经常发现有不少后台程序的性能问题是因为缺少合适索引造成的,有些表甚至一个索引都没有。这种情况往往都是因为在设计表时,没去 定义索引,而开发初期,由于表记录很少,索引创建与否,可能对性能没啥影响,开发人员因此也未多加重视。然一旦程序发布到生产环境,随着时间的推移,表记 录越来越多,这时缺少索引,对性能的影响便会越来越大了。
        这个问题需要数据库设计人员和开发人员共同关注

法则:不要在建立的索引的数据列上进行下列操作:
避免对索引字段进行计算操作
避免在索引字段上使用not,<>,!=
避免在索引列上使用IS NULL和IS NOT NULL
避免在索引列上出现数据类型转换
避免在索引字段上使用函数
避免建立索引的列中使用空值。

3.复杂操作
部分Update、Select 语句 写得很复杂(经常嵌套多级子查询)——可以考虑适当拆成几步,先生成一些临时数据表,再进行关联操作

4.update
同一个表的修改在一个过程里出现好几十次,如:
                update table1
                set col1=…
                where col2=…;
               
                update table1
                set col1=…
                where col2=…
                ……

        象这类脚本其实可以很简单就整合在一个Update语句来完成(前些时候在协助xxx项目做性能问题分析时就发现存在这种情况)

5.在可以使用UNION ALL的语句里,使用了UNION
UNION 因为会将各查询子集的记录做比较,故比起UNION ALL ,通常速度都会慢上许多。一般来说,如果使用UNION ALL能满足要求的话,
                务必使用UNION ALL。还有一种情况大家可能会忽略掉,就是虽然要求几个子集的并集需要过滤掉重复记录,但由于脚本的特殊性,不可能存在重复记录,这时便应该使用 UNION ALL,如xx模块的某个查询程序就曾经存在这种情况,见,由于语句的特殊性,在这个脚本
                中几个子集的记录绝对不可能重复,故可以改用UNION ALL)

6.在Where 语句中,尽量避免对索引字段进行计算操作
                这个常识相信绝大部分开发人员都应该知道,但仍有不少人这么使用,我想其中一个最主要的原因可能是为了编写方便吧,但如果仅为了编
                写简单而损害了性能,那就不可取了

                9月份在对XX系统做性能分析时发现,有大量的后台程序存在类似用法,如:

                ……
                where trunc(create_date)=trunc(:date1)
                虽然已对create_date 字段建了索引,但由于加了TRUNC,使得索引无法用上。此处正确的写法应该是
                where create_date>=trunc(:date1) and create_date<trunc(:date1)+1
                或者是
                where create_date between trunc(:date1) and trunc(:date1)+1-1/(24*60*60)
                注意:因between 的范围是个闭区间(greater than or equal to low value and less than or equal to high value.),
                故严格意义上应该再减去一个趋于0的小数,这里暂且设置成减去1秒(1/(24*60*60)),如果不要求这么精确的话,可以略掉这步

7.对Where 语句的法则
7.1 避免在Where子句中使用in,not  in,or 或者having。
可以使用 exist 和not exist代替 in和not in。
可以使用表链接代替 exist。
Having可以用where代替,如果无法代替可以分两步处理。
例子
Select *  FROM orDERS Where CUSTOMER_NAME NOT IN
                    (Select CUSTOMER_NAME FROM CUSTOMER)
优化
Select *  FROM orDERS Where CUSTOMER_NAME not exist
                    (Select CUSTOMER_NAME FROM CUSTOMER)
7.2 不要以字符格式声明数字,要以数字格式声明字符值。(日期同样)
否则会使索引无效,产生全表扫描。
例子
使用:Select emp.ename, emp.job FROM emp Where emp.empno = 7369;
不要使用:Select emp.ename, emp.job FROM emp Where emp.empno = ‘7369’

8.对Select语句的法则
在应用程序、包和过程中限制使用select * from table这种方式。

例子
使用
Select empno,ename,category FROM emp Where empno = '7369‘
而不要使用
Select * FROM emp Where empno = '7369'

9. 排序
避免使用耗费资源的操作
带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序

10.临时表
慎重使用临时表可以极大的提高系统性能

[SQL]在Sql语句中使用正则表达式来查找你所要的字符

mikel阅读(1048)

这几天有个项目需要从表的某个字段判断是否存在某些规则的字符串,大概如下:

有个表叫TaskDeploy(任务部署的),其中字段Participants以格式 用户名,用户名 具体如下:

 

admin,小明,samlin
小明,samlin,test
samlin,test,小明
samlin,admin
samlin,test
samlin,test

 

好了,现在我要查找有指派给 'samlin'用户的任务记录怎么办?

我首先想到的是正则表达式,但SQL提供的功能真是少啊就是一个 like 加几个通配符,显然是满足不了我的要求的

 

于是从网上搜集了一些资料,整理了一下。
下面这个是一个自定义函数,用户可以调用这个函数判断指定的字符串是否符合正则表达式的规则.

Create FUNCTION dbo.find_regular_expression
 (
  
@source varchar(5000),   需要匹配的源字符串
  @regexp varchar(1000),  正则表达式
  @ignorecase bit = 0  是否区分大小写,默认为false
 )
RETURNS bit  返回结果0-false,1-true
AS
 
BEGIN
 
0(成功)或非零数字(失败),是由 OLE 自动化对象返回的 HRESULT 的整数值。
  DECLARE @hr integer 
用于保存返回的对象令牌,以便之后对该对象进行操作
  DECLARE @objRegExp integer   DECLARE @objMatches integer
保存结果
  DECLARE @results bit
  
/*
创建 OLE 对象实例,只有 sysadmin 固定服务器角色的成员才能执行 sp_OACreate,并确定机器中有VBScript.RegExp类库
*/
  
EXEC @hr = sp_OACreate 'VBScript.RegExp'@objRegExp OUTPUT
  
IF @hr <> 0 BEGIN
   
SET @results = 0
   
RETURN @results
  
END
/*
以下三个分别是设置新建对象的三个属性。下面是'VBScript.RegExp'中常用的属性举例:
    Dim regEx,Match,Matches         '建立变量。
    Set regEx = New RegExp         '建立一般表达式。
    regEx.Pattern= patrn         '设置模式。
    regEx.IgnoreCase = True         '设置是否区分大小写。
    regEx.Global=True                             '设置全局可用性。
    set Matches=regEx.Execute(string)             '重复匹配集合
    RegExpTest = regEx.Execute(strng)      '执行搜索。
   for each match in matches                    '重复匹配集合
   RetStr=RetStr &"Match found at position "
   RetStr=RetStr&Match.FirstIndex&".Match Value is '"
   RetStr=RetStr&Match.Value&"'."&vbCRLF Next
   RegExpTest=RetStr
*/
  
EXEC @hr = sp_OASetProperty @objRegExp'Pattern'@regexp
  
IF @hr <> 0 BEGIN
   
SET @results = 0
   
RETURN @results
  
END
  
EXEC @hr = sp_OASetProperty @objRegExp'Global', false
  
IF @hr <> 0 BEGIN
   
SET @results = 0
   
RETURN @results
  
END
  
EXEC @hr = sp_OASetProperty @objRegExp'IgnoreCase'@ignorecase
  
IF @hr <> 0 BEGIN
   
SET @results = 0
   
RETURN @results
  
END 
调用对象方法
  EXEC @hr = sp_OAMethod @objRegExp'Test'@results OUTPUT, @source
  
IF @hr <> 0 BEGIN
   
SET @results = 0
   
RETURN @results
  
END
释放已创建的 OLE 对象
  EXEC @hr = sp_OADestroy @objRegExp
  
IF @hr <> 0 BEGIN
   
SET @results = 0
   
RETURN @results
  
END
 
RETURN @results
 
END

 

下面是一个简单的测试SQL语句,可以直接在查询分析器中运行。

 

DECLARE @intLength AS INTEGER
DECLARE @vchRegularExpression AS VARCHAR(50)
DECLARE @vchSourceString as VARCHAR(50)
DECLARE @vchSourceString2 as VARCHAR(50)
DECLARE @bitHasNoSpecialCharacters as BIT
 初始化变量
SET @vchSourceString = 'Test one This is a test!!'
SET @vchSourceString2 = 'Test two This is a test'
 我们的正则表达式应该类似于
 [a-zA-Z ]{}
 如: [a-zA-Z ]{10}    一个十字符的字符串

 获得字符串长度
SET @intLength = LEN(@vchSourceString)
 设置完整的正则表达式
SET @vchRegularExpression = '[a-zA-Z ]{' + CAST(@intLength as varchar+ '}'
 是否有任何特殊字符
SET @bitHasNoSpecialCharacters = dbo.find_regular_expression(@vchSourceString@vchRegularExpression,0)
PRINT @vchSourceString
IF @bitHasNoSpecialCharacters = 1 BEGIN
 
PRINT 'No special characters.'
END ELSE BEGIN
 
PRINT 'Special characters found.'
END
PRINT '**************'
 获得字符串长度
SET @intLength = LEN(@vchSourceString2)
 设置完整的正则表达式
SET @vchRegularExpression = '[a-zA-Z ]{' + CAST(@intLength as varchar+ '}'
 是否有任何特殊字符
SET @bitHasNoSpecialCharacters = dbo.find_regular_expression(@vchSourceString2@vchRegularExpression,0)
PRINT @vchSourceString2
IF @bitHasNoSpecialCharacters = 1 BEGIN
 
PRINT 'No special characters.'
END ELSE BEGIN
 
PRINT 'Special characters found.'
END
GO

 

最后得出的查询语句如下:

 

select * FROM TaskDeploy  where  1=1  And dbo.find_regular_expression(Participants,'\bsamlin\b',0= 1 

查找出包含 samlin 用户名记录的任务

但用函数的可能效率不知怎么样,下次测试一下

不知大家有没更好的方法?

 

转载请注明出处[http://samlin.cnblogs.com/

[服务器]Lighttpd 与 Apache

mikel阅读(817)

Security, speed, compliance, and flexibility — all of these describe lighttpd (pron. lighty) which is rapidly redefining efficiency of a webserver; as it is designed and optimized for high performance environments. With a small memory footprint compared to other web-servers, effective management of the cpu-load, and advanced feature set (FastCGI, SCGI, Auth, Output-Compression, URL-Rewriting and many more) lighttpd is the perfect solution for every server that is suffering load problems. And best of all it's Open Source licensed under the revised BSD license.

网址:http://www.Lighttpd.net

简介:

Web 2.0

lighttpd powers several popular Web 2.0 sites like YouTube, wikipedia and meebo. Its high speed io-infrastructure allows them to scale several times better with the same hardware than with alternative web-servers.

This fast web server and its development team create a web-server with the needs of the future web in mind:

Its event-driven architecture is optimized for a large number of parallel connections (keep-alive) which is important for high performance AJAX applications.

Downloads

[C#]Asp.Net Mvc: 浅析TempData机制

mikel阅读(855)

环境:

Windows 2008, VS 2008 SP1, ASP.NET Mvc 1.0

——————————————————————————

一. ASP.NET Mvc中的TempData

ASP.NET Mvc框架的ControllerBase中存在一个叫做TempData的Property,它的类型为TempDataDictionary,顾名思 义是一个字典类。TempData在ASP.NET MVC中的作用是:可用于在Action执行过程之间传值。简单的说,你可以在执行某个Action的时候,将数据存放在TempData中,那么在下一 次Action执行过程中可以使用TempData中的数据。

如:

上面的代码中,Index()给TempData添加了一个键值对,假设我们先请求Index这个Action,接着请求Index2这个 Action,那么在Index2中,我们便可以得到之前添加到TempData的键值对。有趣的是,这时如果再次请求Index2,那么从 TempData中读到的MyName的值会是null。于是,我们需要了解TempData的生命周期。

二. TempData的生命周期

我们知道Http是无状态的,为什么TempData可以在两次请求之前传递数据呢?很明显,这个数据必定是已某种形式保存了。查看Controller类的源代码,很容易的找到了我们想要的东西:

从上面的代码可以看出,每次在执行Action之前,都要调用一下TempData.Load()方法,执行完Action之后,再调用一下TempData.Save()方法。另外这里还有一个重要成员TempDataProvider。

阅读了相关源代码之后,真相大白了。

TempData.Load()

TempData.Save()

TempDataProvider 用于暂存数据。在TempData.Load()方法中,TempDataProvider中保存的数据会被读到TempData中,供Action调用 过程中使用。Action执行完后,TempData.Save()所作的事情则是,移除TempData中任何没有被更新的键值对,然后再将 TempData中的数据保存,供下一次调用使用(注:也就是说,只有更新过的,以及新添加的键值对才能再下次request中继续使用)。为什么 TempData中的数据需要迅速被清除呢?很简单,节约内存嘛。

三. ITempDataProvider

前面提到的TempDataProvider是Controller的一个Property,它的定义是这样的:

这里我们看到了一个默认实现的SessionStateTempDataProvider类。也就是说,默认情况下,ASP.NET MVC通过SessionStateTempDataProvider来保存TempData的数据。很明显,数据是存在Session中的,也就是说, 如果你禁用SessionState,那么你的页面就报异常了。

ASP.NET MVC生来就是被设计为易扩展的,我们可以很容易通过实现自己的ITempDataProvider类来替换这个默认的 SessionStateTempDataProvider。需要注意的是,TempDataProvider存放的数据必需具有用户独立性。

ITempDataProvider接口定义非常简单:

在MvcFutures中,你也可以找到一个CookieTempDataProvider,提供了将TempData存储在Cookie中的实现。

Copyright

作者: Tristan G
本文版权归作者和博客园共有,欢迎转载 🙂

[C#]ASP.NET MVC 多语言解决方案

mikel阅读(1047)

    现在ASP.NET MVC 已经出了第四版了,现在多了很多特性,但是如何在 ASP.NET MVC 下方便的实现多语言特性呢?

就一个网站的多语言特性来说,我认为分为两个方面:

1、HTML界面上显示的文字需要多语言

2、HTML界面上JS输出的文字需要多语言

原来在HTML部分直接写的文字都不能直接写要输出的文字,而是要采用标记的方法来替换。JS也是同理。

那么在MVC下怎么能透明的实现多语言呢?所谓透明的实现是指,程序员在开发程序当中,不需要过多的考虑多语言的问题,直接调用一个方法就能实现多语言,而且所要用到的语言文件每个语言一个文件就够了,集中翻译这个语言就完成了多语言的功能。

例如
<html>

<head>

</head>

<body>

   多语言输出的文字  //这里就不能直接写中文了,一个好方法是 直接用 <%= Html.Lang("string1") %> 来进行输出

</body>

</html>

这里<%= Html.Lang("clickme") %> 是对 HTMLHelper 进行了扩展,增加了一个 Lang 的方法,参数是需要翻译的资源字符串的Name。

 怎么为 HTMLHelper 进行扩展?下面这个类就是增加了的扩展类

 

 


using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Globalization;
using System.Web.Compilation;
using System.Web.Mvc;
using System.Web.Routing;
namespace System.Web.Mvc {
    
public static class LocalizationHelpers {
        
/// <summary>
        
/// 在外边的 Html 中直接使用
        
/// </summary>
        
/// <param name="htmlhelper"></param>
        
/// <param name="key"></param>
        
/// <returns></returns>
        public static string Lang(this HtmlHelper htmlhelper, string key) {
            
string FilePath = htmlhelper.ViewContext.HttpContext.Server.MapPath("/"+ "Resource\\";
            
return GetLangString(htmlhelper.ViewContext.HttpContext, key, FilePath);
        }
        
/// <summary>
        
/// 在外边的 Html 中直接使用,对 JS 进行输出字符串
        
/// </summary>
        
/// <param name="htmlhelper"></param>
        
/// <param name="key"></param>
        
/// <returns></returns>
        public static string LangOutJsVar(this HtmlHelper htmlhelper, string key) {
            
string FilePath = htmlhelper.ViewContext.HttpContext.Server.MapPath("/"+ "Resource\\";
            
string langstr = GetLangString(htmlhelper.ViewContext.HttpContext, key, FilePath);
            
return string.Format("var {0} = '{1}'", key,langstr);
        }
        
/// <summary>
        
/// 在 C# 中使用
        
/// </summary>
        
/// <param name="httpContext"></param>
        
/// <param name="key"></param>
        
/// <returns></returns>
        public static string InnerLang(HttpContextBase httpContext, string key) {
            
string FilePath = httpContext.Server.MapPath("/"+ "Resource\\";
            
return GetLangString(httpContext, key, FilePath);
        }
        
private static string GetLangString(HttpContextBase httpContext, string key, string FilePath) {
            LangType langtype 
= LangType.cn;
            
if (httpContext.Session["Lang"!= null) {
                langtype 
= (LangType)httpContext.Session["Lang"];
            }
            
return LangResourceFileProvider.GetLangString(key, langtype, FilePath);
        }
    }
    
public static class LangResourceFileProvider {
        
public static string GetLangString(string Key, LangType langtype, string FilePath) {
            
string filename;
            
switch (langtype) {
                
case LangType.cn: filename = "zh-cn.resources"break;
                
case LangType.en: filename = "en-us.resources"break;
                
default: filename = "zh-cn.resources"break;
            }
            System.Resources.ResourceReader reader 
= new System.Resources.ResourceReader(FilePath + filename);
            
string resourcetype;
            
byte[] resourcedata;
            
string result = string.Empty;
            
try {
                reader.GetResourceData(Key, 
out resourcetype, out resourcedata);
                
//去掉第一个字节,无用
                byte[] arr = new byte[resourcedata.Length  1];
                
for (int i = 0; i < arr.Length; i++) {
                    arr[i] 
= resourcedata[i + 1];
                }
                result 
= System.Text.Encoding.UTF8.GetString(arr);
            }
            
catch (Exception ex) {
            }
            
finally {
                reader.Close();
            }
            
return result;
        }
    }
    
public enum LangType {
            cn,
            en
        }
}

 这个类叫 LocalizationHelpers ,公开了 Lang,LangOutJsVar,InnerLang 三个方法,其中 Lang,LangOutJsVar 可以在 Html 界面中直接调用,InnerLang 可以在C#后台使用。

这里使用了 .resx 资源文件,注意这里这个文件需要被编译后才能使用,否则找不到已经增加的项。编译这个可以使用.NET 自带的 ResGen.exe。

上面这个类很简单,就是根据传入的 Session["Lang"] 中的语言类型来做判断,该读那个资源文件(资源文件必须在 Resource 目录下),然后读取所需要的NAME,返回对应的字符串VALUE,VALUE中就是最后要输出的文字了。

 

在前台的 .aspx 中就可以直接用  <%= Html.Lang("String1") %>来输出了。至于JS的输出,看下面例子

    <script language="JavaScript" type="text/JavaScript">
    <%= Html.LangOutJsVar("msg")%>
        function show()
        {
            alert(msg);
        }
    </script>

这样就OK了。

如果有的需要在C#中取资源字符串,那么可以使用           

ViewData["Message"] = LocalizationHelpers.InnerLang(this.ControllerContext.HttpContext, "Welcome");来输出。

我根据ASP.NET MVC 4做了个DEMO,截图如下


具体代码点击下载

[C#]扩展ASP.NET MVC HtmlHelper类

mikel阅读(972)

原文地址:Extending ASP.NET MVC HtmlHelper Class

在这篇帖子中我会使用一个示例演示扩展ASP.NET MVC HtmlHelper类,让它们可以在你的MVC视图中工作。这个示例中我会提供一个简单的方案生成Html表格。

HtmlHelper类

HtmlHelper类用于在ASP.NET MVC framework中帮助视图呈现html部分。

这个类提供了一些方法,你可以使用这些方法呈现html中的一些类型(textbox,checkbox等),或者html的一部分(如form)。ASP.NET MVC framework helper有这些内容:

  • Html.ActionLink()
  • Html.BeginForm()
  • Html.CheckBox()
  • Html.DropDownList()
  • Html.EndForm()
  • Html.Hidden()
  • Html.ListBox()
  • Html.Password()
  • Html.RadioButton()
  • Html.TextArea()
  • Html.TextBox()

比如说你要显示一个用name属性为myChkbox并且已经勾选的复选框,可以这样写:

<%=Html.CheckBox(“myChkbox”, true) %>

所有的html helper都是由扩展方法创建的,设在System.Web.Mvc.Html名称空间。

为HtmlHelper创建Html表格扩展

在本示例中我写了一个扩展方法,用于支持html表格的呈现。你可以修改它或者创建你自己的示例。

public static class MVCHelpers
{
    public static string Table(this HtmlHelper helper, string name, IList items, IDictionary<string, object> attributes)
    {
        if (items == null || items.Count == 0 || string.IsNullOrEmpty(name))
        {               
            return string.Empty;
        }
        return BuildTable(name, items, attributes);           
    }
    private static string BuildTable(string name, IList items, IDictionary<string, object> attributes)
    {
        StringBuilder sb = new StringBuilder();
        BuildTableHeader(sb, items[0].GetType());
        foreach (var item in items)
        {
            BuildTableRow(sb, item);
        }
        TagBuilder builder = new TagBuilder("table");
        builder.MergeAttributes(attributes);
        builder.MergeAttribute("name", name);
        builder.InnerHtml = sb.ToString();           
        return builder.ToString(TagRenderMode.Normal);
    }
    private static void BuildTableRow(StringBuilder sb, object obj)
    {
        Type objType = obj.GetType();
        sb.AppendLine("\t<tr>");
        foreach (var property in objType.GetProperties())
        {
            sb.AppendFormat("\t\t<td>{0}</td>\n", property.GetValue(obj, null));
        }
        sb.AppendLine("\t</tr>");
    }
    private static void BuildTableHeader(StringBuilder sb, Type p)
    {
        sb.AppendLine("\t<tr>");
        foreach (var property in p.GetProperties())
        {
            sb.AppendFormat("\t\t<th>{0}</th>\n", property.Name);
        }
        sb.AppendLine("\t</tr>");
    }
}

你可以看到我如何利用扩展方法Table扩展HtmlHelper类。BuildTable方法是主要方法,它利用ASP.NET MVC TagBuilder类来创建table标签。你可以看到在我的示例用,我使用了反射,获取各项的属性列表,并且把这些属性名称作为表头,它们的值填充为 表格单元格。

在视图中使用Html.Table扩展方法

如果你想使用这个自定义html helper,只需要做这些:

  • 在视图中用注册helper所在的名称空间:<%@ Import Namespace=”TaskList.Models” %>
  • 使用视图的Html属性中的Table方法,例如创建一个name属性为myTable,并使用视图中当前模型的例 子:<%=Html.Table(”myTable”, (IList)ViewData.Model, null) %>,注意Model如果不是IList,会出现异常。

总结

在这篇帖子中我介绍了HtmlHelper类,和如何为这个类创建一个简单的扩展方法。也可以通过创建你自己的类(如TableHelper)来扩展 HtmlHelper,你需要做的只是创建方法,并返回所要呈现的html。在我看来,使用扩展方法比较简单一点。

[C#]ASP.NET MVC 1.0开源

mikel阅读(985)

最新消息:ASP.NET MVC使用微软的开源许可协议发布了。Microsoft Public License已由Open Source Initiative组织认证,适合大部分需要开源许可的项目使用,其中包括Novell的Mono。

目前我们无法解释微软为何使用这种方式发布框架,不过我们已经向Scott Guthrie确认了一点,那就是这些代码并没有平台限制。据推测,这些代码也可以被移植到Java或Ruby平台中去,不过既然已经有了SpringRuby on Rails框架,因此这方面的需求应该几乎为零。

您可以在微软下载中心获取到ASP.NET MVC源代码

查看英文原文:ASP.NET MVC is Open Source

[C#]无缝缓存读取简化:仅Lambda表达式传递委托

mikel阅读(544)

之前写了一篇:无缝的缓存读取:双存储缓存策略,其中使用了两个存储地址交替提供缓存数据。

在其中用了两个存储指针转换以达到无缝读取缓存,在Cat Chen一语提醒之后,想了一想:的确是没有必要在缓存中使用两个存储指针的,其实一个存储地址,只要保证写入时在其它线程就可以。

更改存储介质至以下两个属性:

namespace CHCache {
/// <summary>
/// 缓存介质
/// </summary>
public class Medium {
/// <summary>
/// 存储区
/// </summary>
public object Store { get; set; }
/// <summary>
/// 是否正在更新
/// </summary>
public bool IsUpdating { get; set; }
}
}

这里存储区用于存储要缓存的实体内容,而IsUpdating则标识其是否正在更新。

对于缓存类,则更改了写入和读取方式。

/*
* http://www.cnblogs.com/chsword/
* chsword
* Date: 2009-3-31
* Time: 17:00
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace CHCache {
/// <summary>
/// 双存储的类
/// </summary>
public class DictionaryCache : IEnumerable {
/// <summary>
/// 在此缓存构造时初始化字典对象
/// </summary>
public DictionaryCache() {
Store = new Dictionary<string, Medium>();
}
public void Add(string key, Func<object> func) {
if (Store.ContainsKey(key)) {//修改,如果已经存在,再次添加时则采用其它线程
var elem = Store[key];
if (elem.IsUpdating) return;  //正在写入未命中
var th = new ThreadHelper(elem, func);
var td = new Thread(th.Doit);
td.Start();
}
else {//首次添加时可能也要读取,所以要本线程执行
Console.WriteLine("Begin first write");
Store.Add(key, new Medium { Store = func() });
Console.WriteLine("End first write");
}
}
/// <summary>
/// 读取时所用的索引
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object this[string key] {
get {
if (!Store.ContainsKey(key)) return null;
var elem = Store[key];
return elem.Store;
}
}
Dictionary<string, Medium> Store { get; set; }
public IEnumerator GetEnumerator() {
return ((IEnumerable)Store).GetEnumerator();
}
}
}

这里在添加时只控制了首次写入缓存在主线程,而读取时则直接读取缓存内容。

而线程辅助类也进行了简化,仅将其执行并写入就好了,抛出线程完全由DictionaryCache控制。

using System;
namespace CHCache {
/// <summary>
/// 一个线程Helper,用于帮助多抛出线程时传递参数
/// </summary>
public class ThreadHelper {
Func<object> Fun { get; set; }
Medium Medium { get; set; }
/// <summary>
/// 通过构造函数来传递参数
/// </summary>
/// <param name="m"></param>
/// <param name="fun"></param>
public ThreadHelper(Medium m, Func<object> fun) {
Medium = m;
Fun = fun;
}
/// <summary>
/// 线程入口,ThreadStart委托所对应的方法
/// </summary>
public void Doit() {
Medium.IsUpdating = true;
Console.WriteLine("Begin write.");
var ret = Fun.Invoke();
Medium.Store = ret;
Console.WriteLine("End write.");
Medium.IsUpdating = false;
}
}
}

其实有的时候思考问题还是不由自主的向着自己的经验方向刻意安排,这样通常把问题搞复杂了。

还好有园子里的朋友帮助,才简单的解决了问题,这样的由简至繁,再由繁衍至简的过程其实在实际开发中发生的还真不少。

 

[C#]ASP.NET MVC Training Kit发布了

mikel阅读(727)

Scott Guthrie昨天宣布了ASP.NET MVC 按照Ms-PL协议开源发布,具体内容参见ASP.NET MVC 1.0 has been released,也可以参看Scott Hanselman的新闻稿Microsoft ASP.NET MVC 1.0 is now Open Source MS-PL

微软同时也推出了一套ASP.NET MVC frameworke培训教材, 其中包含了许多范例程序、PPT、实验演练(Labs)教材等,想学习新技术的人不用在等了,赶快下载回来学习吧。

下面是主要内容截图:

image

 image

作者: 自由、创新、研究、探索……
出处:http://shanyou.cnblogs.com/
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://www.openbeta.cn

[Flash]flash跨域名动态加载数据

mikel阅读(752)

    以前开发的一个页面功能是由flash实现的,考虑到用户体验的连续性,flash与后台的交互不能通过普通的getURL的方式实现(否则每次交互都会导致页面刷新,用户体验很差),而必须用AS里面的LoadVars类来实现动态加载。
    通常活动开发的相关flash会放在html/…/promote目录下面(对应promote域名),而cgi会放在cgi-bin /service目录下面(对应service域名)。结果发现这个flash总是加载不到cgi输出的信息。把cgi移到cgi-bin /promote目录(对应promote域名),flash就可以加载到cgi的输出信息。看apache日志也发现:cgi放在promote目录, 就有HTTP请求;cgi放到service目录,则flash居然连访问cgi的请求包都没发送。很奇怪。
    通过HTTP Watch仔细对比两种情况下的请求,发现后者多了下面这个请求:
00:00:00.231 0.525 521 GET 404 text/html: charset=iso-88…  http://service.paipai.com/crossdomain.xml
    看看名字,估计就是flash对跨域加载数据作了安全性限制。baidu一番以后,在html/…/service目录添加crossdomain.xml文件,内容如下:
<?xml version="1.0"?>
<cross-domain-policy>
  <allow-access-from domain="*.paipai.com" />
</cross-domain-policy>
    这个xml文件的格式很简单,就不多解释了。加了这个文件以后,LoadVars类就可以从paipai.com的任何一个子域名访问到service域名的cgi了。
    如果不希望所有cgi都能随便访问,那么需要再作精细化配置,诸位可自行研究。