
14年企业级软件及互联网产品研丰富发经验,曾任国内知名软件外包企业高级项目经理、手游公司技术总监。现任深圳前海童育汇电子商务股份有限公司产品研发负责人。
我们常常会遇到需要利用并行处理,尽量发挥多核或多CPU的潜能,提高程序运行效率的场景。在.NET环境下,常用的做法是使用Thread,多线程方式进行并行处理。但在.Net4.0中,微软提供一种新的概念——Task(任务),换句话说,并行处理由“多线程”进化为了“多任务”的方式。 一、利用Task实现多任务处理 测试1: 以下为测试过程,模拟多次调用一耗时方法,分别使用串行、多线程方式、多任务方式: 1、建立一虚拟耗时的方法 /// <summary>/// 模拟执行耗时的方法/// </summary> public static void TestLongTimeMethod() { Console.WriteLine("method start:" + System.DateTime.Now.ToString()); System.Threading.Thread.Sleep(5000); Console.WriteLine("method end:" + System.DateTime.Now.ToString()); } 2、传统串行调用方式、多线程调用、多任务调用 #region 传统串行方式/// <summary>/// 传统串行方式/// </summary> public static void lineMethod() { TestLongTimeMethod(); TestLongTimeMethod(); TestLongTimeMethod(); }#endregion #region 多线程方式/// <summary>/// 多线程方式/// </summary> public static void threadMethod() {var thread1 = new Thread(() => TestLongTimeMethod());var thread2 = new Thread(() => TestLongTimeMethod()); thread1.Start(); thread2.Start(); TestLongTimeMethod(); thread1.Join(); thread2.Join(); }#endregion #region 多任务方式/// <summary>/// 多任务方式——线程池中,委托给CPU,全部执行完后再跳出线程池/// </summary> public static void taskMethod() {// 方式1:使用Parallel.Invoke,可同时并行多个任务,任务调用的方法可以不同//Parallel.Invoke(// () => TestLongTimeMethod(),// () => TestLongTimeMethod(),// () => TestLongTimeMethod()//);// 方式2:使用Parallel.For,可设定并行多个任务,任务调用的方法相同 int times = 3; Parallel.For(0, times, i => TestLongTimeMethod() ); }#endregion 3、模拟执行过程,统计过程用时 static void Main(string[] args) {int maxTimes = 1; DateTime ds = new DateTime(); DateTime de = new DateTime(); DateTime ds1 = new DateTime(); DateTime de1 = new DateTime(); DateTime ds2 = new DateTime(); DateTime de2 = new DateTime();#region lineMethod 串行 Console.WriteLine("**************【串 行】**************"); ds = DateTime.Now; Console.WriteLine("**************[StartTime:" + ds.ToString() + "]**************");for (int intLoop = 0; intLoop < maxTimes; intLoop++) { Console.WriteLine("**************[" + (intLoop + 1).ToString() + "]**************"); lineMethod(); } de = DateTime.Now; Console.WriteLine("**************[EndTime:" + de.ToString() + "]**************"); System.Threading.Thread.Sleep(500);#endregion #region threadMethod 多线程 Console.WriteLine("**************【多线程】**************"); ds1 = DateTime.Now; Console.WriteLine("**************[StartTime:" + ds1.ToString() + "]**************");for (int intLoop = 0; intLoop < maxTimes; intLoop++) { Console.WriteLine("**************[" + (intLoop + 1).ToString() + "]**************"); threadMethod(); } de1 = DateTime.Now; Console.WriteLine("**************[EndTime:" + de1.ToString() + "]**************"); System.Threading.Thread.Sleep(500);#endregion#region taskMethod 多任务 Console.WriteLine("**************【多任务】**************"); ds2 = DateTime.Now; Console.WriteLine("**************[StartTime:" + ds2.ToString() + "]**************");for (int intLoop = 0; intLoop < maxTimes; intLoop++) { Console.WriteLine("**************[" + (intLoop + 1).ToString() + "]**************"); taskMethod(); } de2 = DateTime.Now; Console.WriteLine("**************[EndTime:" + de2.ToString() + "]**************"); System.Threading.Thread.Sleep(500);#endregion Console.WriteLine("lineMethod 【串 行】 : " + (de - ds).TotalMilliseconds.ToString()); Console.WriteLine("threadMethod【多线程】 : " + (de1 - ds1).TotalMilliseconds.ToString()); Console.WriteLine("taskMethod 【多任务】 : " + (de2 - ds2).TotalMilliseconds.ToString()); Console.ReadLine(); } 4、执行结果截图 结论:从结果可以看出多线程或多任务的性能明显高于串行方式。多线程或多任务执行效率区别不大,.NET框架底层实现可能大致相同。但多任务的代码写法更为简洁,也更为灵活。 二、利用Task实现并行、串行的执行顺序定义 测试2:: 1、假定A、B、C、D、E 多任务的执行顺序为:A、B 执行后,执行C,A 执行后,执行 D, B 执行后,执行 E执行时的测试方法如下(即执行时显示执行的名称,并按传入的时间参数,决定进程休眠的时间): public class TestAction {private int _p;private string _actionName;public TestAction(string actionName, int p) { _actionName = actionName; _p = p; }public void Do() { Console.WriteLine(System.DateTime.Now.ToString() + " | 开始执行" + _actionName); Thread.Sleep(new TimeSpan(0, 0, _p)); Console.WriteLine(System.DateTime.Now.ToString() + " | 执行完毕" + _actionName); } } 2、测试方法(传统串行、串并行结合) 假定各任务分别耗时为A(5秒)、B(5秒)、C(2秒)、D(1秒)、E(2秒)。则串行需用时5+5+2+1+2=15 秒,串并行结合(A、B -> C,A -> D,B -> E) 需用时 5+2 = 7 秒. 测试程序如下: /// <summary>/// 按设计的顺序测试(同时考虑串行与并行): A、B -> C,A -> D,B -> E/// </summary> public static void SortTaskMethod() { Console.WriteLine("--------------[串行]--------------"); (new TestAction("A", 5)).Do(); (new TestAction("B", 5)).Do(); (new TestAction("C", 2)).Do(); (new TestAction("D", 1)).Do(); (new TestAction("E", 2)).Do(); Console.WriteLine("--------------[多任务]--------------"); TaskFactory factory = new TaskFactory(); Task a = factory.StartNew((new TestAction("A", 5)).Do); Task b = factory.StartNew((new TestAction("B", 5)).Do); Task c = factory.ContinueWhenAll(new Task[] { a, b }, ((preTasks) => (new TestAction("C", 2)).Do())); Task d = factory.ContinueWhenAll(new Task[] { a }, ((preTasks) => (new TestAction("D", 1)).Do())); Task e = factory.ContinueWhenAll(new Task[] { b }, ((preTasks) => (new TestAction("E", 2)).Do())); } 3、执行结果截图 结论:与测试预想结果一致 实现的关键代码: // 声明并获取一个Task工厂实例TaskFactory factory = new TaskFactory();// 利用工厂创建一个任务,并执行指定的方法Task a = factory.StartNew((new TestAction("A", 5)).Do); // 利用工厂创建后续任务(根据前置任务),并执行指定的方法Task c = factory.ContinueWhenAll(new Task[] { a, b }, ((preTasks) => (new TestAction("C", 2)).Do())); 请注意以上使用工厂方式获得的任务实例,与之前介绍的Parallel.Invoke 方式,二者有很重要的区别:工厂方式获取任务实例后即分配给系统委托,不受当前调用的方法约束;但invoke方式,括号内部声明的多个任务,必须全部执行结束,才会跳出invoke,回到当前调用的方法中。
C#中如果采用Process调用应用程序失败,请添加下列第一行,设置应用程序所在的路径。 Directory.SetCurrentDirectory([应用程序所在路径]); Process process = new Process(); process.StartInfo.FileName = [应用程序名称]; process.StartInfo.Arguments = [调用参数]; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.Start(); process.WaitForExit();
1、客户端:一个IT经理走进一家拉面馆说:“你们需要客户端吗?” 老板说:“面一般是伙计端,忙的时候才需要客户端。” 2、云计算:中国一留学生去美国打工的当过报童,不带计算器,习惯动作抬头望天时心算找零。顾客大为惊讶,纷纷掏出计算器验证,皆无误,也抬头望天,惊恐问:“云计算?” 3、1k=1024:A:哥们,最近手头紧,借点钱吧?B:好啊,要多少?A:一千行不?B:咱俩谁跟谁!给你凑个整数,这有一千零二十四,拿去。 4、GeForce:一直觉得NVIDIA应该把“GeForce“更名为“GeiForce”,中文翻译为“给力!” 5、反括号:据说某俄国特工九死一生偷到了美国NASA太空火箭发射程序源代码的最后一页,结果代码是:“}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}” 6、IDE:A:为什么你的关键字会变蓝,我的没有? B:(看了一下,没来及说话)A:为什么我的字下面有波浪线,你的没有? B:你为什么开个Word来编程?
今日,网上偶然看到360安全卫士提醒更新——“360隐私保护器”。 真是不用不知道,一用吓一跳,大家天天使用的腾讯QQ,居然是潜伏在我们电脑里的一个重大特务分子,幸好360将其揪了出来。先不论360安全卫士出于什么样的目的,商业竞争或者真为网民办实事,腾讯QQ这次小辫子真是被牢牢抓住了。 启动QQ五分钟以上时,果然如360所说,腾讯对非QQ程序之外的其他应用程序的监视开始了,主流的软件真是一个都没逃脱: 即时聊天工具:MSN、飞信、Skype 视频:土豆、PPStream 文档:word、excel、ppt 压缩包:zip、rar 安全:360安全卫士 输入法:搜狗拼音 浏览器:傲游 下载:迅雷、电骡 ……(我本地安装的程序有限,QQ实际跟踪监视的软件应该更多) QQ,你个聊天工具不安分守己做好自己的事,看我电脑里的其他程序是何居心?诚然你现在是互联网公敌,在各个领域都有重量级的竞争对手,但你在我的电脑里看别人做事情干嘛呢? 如果说查看你竞争对手的程序,可解释为:为自己同类型产品的用户体验改善而进行的一点小偷行为。但尤为重要的是:对于俺办公类应用程序的监控,你的居心何在?为什么要看我的文件?这样做真是不可饶恕!!你这样做的后果,只能是让长久以往培养出来的客户群失去对你的信赖,如果十几亿网民只要打开QQ干别的事情时,一举一动都处在你的严密监视之中,个人隐私或者商业机密如何保证?那大家应采取的方式只能是不使用QQ,改为其他即时通讯工具MSN或者SKYPE,虽然不及你本土化做得够,但人家基本的即时通讯功能没有丧失,只是没有你附加的那些花花草草的东西。看来很多公司内部网络上对QQ的封杀的确是相当明智的做法。 进一步讲,如果仅QQ这一工具就对我们的机器有了如此的监控,那么腾讯开发的其他工具又能让人放心吗?东方不亮西方亮,搞不好,明天QQ更新版本,不做这些监控了。不过却转移到QQ游戏、QQ音乐、QQ旋风下载之类的客户端工具上去,谁说得定呢? 早些年,听说QQ为了改善用户体验,悄悄地对用户在QQ客户端上的所有行为进行了记录,不过出发点是好的,做得还不算过分,仅限于自身软件用户行为的记录。可现在你这样将监控范围无限制的扩大化,远超出了改善QQ软件本身用户体验而收集用户隐私的范畴。点解啊?莫非处于某种不可告人的目的,莫非也不是你自愿的,而是中国特色的互联网环境“逼”着你监控大家的。如果这样,那你确实也没办法去掉这些隐私监控的小偷行为,那俺们只有另换一种相对信息安全一点的即时通讯工具了。如果360借此机会推出自己的即时通讯工具,不妨暂时一试。 别了,腾讯QQ。别了,腾讯所有的“山寨”应用。尽管哥现在已经不常用QQ了,不过还有很多亲戚朋友、哥们弟兄天天在QQ上面耗着,给大家提个醒。小心为妙!
vs2008支持.net3.5,而vs2005支持.net2.0,所以使用vs2005打开vs2008的项目,要确定你的项目是.net2.0的。下面介绍2种方法:方法1:用记事本打开.sln文件,你将看到Microsoft Visual Studio Solution File, Format Version 10.00# Visual Studio 2008你把它改成:Microsoft Visual Studio Solution File, Format Version 9.00# Visual Studio 2005即可用2005来打开 方法2:1. 用记事本打开解决方案文件[解决方案名].sln,然后修改最上面两行为如下代码:Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 20052. 用记事本打开每个项目文件[项目名].csproj,在<PropertyGroup>节点下移除如下节点:<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>并且修改ProductVersion和Import两个节点为如下:<ProductVersion>8.0.50727</ProductVersion><Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />这样应该就可以打开了。
Oracle Conversion Functions Version 11.1 Note: Functions for converting to date, numeric, string, and timestamp data types can be found through the related links. ASCIISTR Converts An ASCII String To An ASCII String In The Database's Character Set ASCIISTR(ch VARCHAR2 CHARACTER SET ANY_CS)RETURN VARCHAR2 CHARACTER SET ch%CHARSET; SELECT ASCIISTR(CHR(128) || 'Hello' || CHR(255))FROM dual; BFILENAME Returns a BFILE from a combination of a directory and a file name BFILENAME(directory IN VARCHAR2, filename IN VARCHAR2) RETURN BFILE; DECLARE src_file BFILE;BEGIN src_file := bfilename('CTEMP', 'myfile.txt');END;/ BIN_TO_NUM Converts a bit vector to a number BIN_TO_NUM(<value>,<value>,....) SELECT BIN_TO_NUM(1, 0, 1, 0) FROM dual; CAST Converts one built-in datatype or collection-typed value into another built-in datatype or collection-typed value CAST(<string_or_column> AS <DATATYPE>) SELECT CAST(15402 AS VARCHAR2(30))FROM dual; CHARTOROWID Converts a value from CHAR, VARCHAR2, NCHAR, or NVARCHAR2 datatype to ROWID datatype CHARTOROWID(<char>); conn hr/hrSELECT rowidFROM employees;SELECT last_nameFROM employeesWHERE ROWID = CHARTOROWID('AAAQvRAAFAAAABYAAp'); COMPOSE Convert a string in any data type to a Unicode string COMPOSE(<string_or_column>) Unistring Value Resulting character unistr('\0300') grave accent (`) unistr('\0301') acute accent (? unistr('\0302') circumflex (ˆ) unistr('\0303') tilde (~) unistr('\0308') umlaut (? SELECT 'ol' || COMPOSE('e' || UNISTR('\0301')) FROM dual; CONVERT Converts a character string from one character set to another CONVERT(<char>, <dest_char_set>, <source_char_set>) SELECT CONVERT('?????A B C D E','US7ASCII','WE8ISO8859P1')FROM dual; DECOMPOSE Converts a unicode string to a string DECOMPOSE(<unicode_string>) SELECT DECOMPOSE('ol' || COMPOSE('e' || UNISTR('\0301')))FROM dual; HEXTORAW Converts char containing hexadecimal digits in the CHAR, VARCHAR2, NCHAR, or NVARCHAR2 character set to a raw value HEXTORAW(<hex_value>) CREATE TABLE test (raw_col RAW(10));desc testINSERT INTO test VALUES (HEXTORAW('7D'));SELECT * FROM test; NUMTODSINTERVAL Converts a number to an INTERVAL DAY TO SECOND literal NUMTODSINTERVAL(n, <interval_unit>) SELECT NUMTODSINTERVAL(120, 'DAY') FROM dual;SELECT NUMTODSINTERVAL(1200, 'HOUR') FROM dual;SELECT NUMTODSINTERVAL(12000, 'MINUTE') FROM dual;SELECT NUMTODSINTERVAL(120000, 'SECOND') FROM dual; NUMTOYMINTERVAL Converts n to an INTERVAL YEAR TO MONTH literal NUMTOYMINTERVAL(n, <interval_unit>) conn hr/hrSELECT last_name, hire_date, salary, SUM(salary) OVER (ORDER BY hire_date RANGE NUMTOYMINTERVAL(1, 'YEAR') PRECEDING) AS t_salFROM employees; RAWTOHEX Converts raw to a character value containing its hexadecimal equivalent RAWTOHEX(<raw_value>) CREATE TABLE test (raw_col RAW(10));desc testINSERT INTO test VALUES (HEXTORAW('7D'));SELECT * FROM test;SELECT RAWTOHEX(raw_col) HEXVALFROM test; RAWTONHEX Converts raw to an NVARCHAR2 character value containing its hexadecimal equivalent RAWTONHEX(<raw_value>); col dumpcol format a30SELECT RAWTONHEX(raw_col) HEXVAL, dump(raw_col) dumpcolFROM test; REFTOHEX Converts argument expr to a character value containing its hexadecimal equivalent. expr must return a REF. REFTOHEX(<expr>); conn oe/oeCREATE TABLE warehouse_table OF warehouse_typ(PRIMARY KEY (warehouse_id));CREATE TABLE location_table (location_number NUMBER,building REF warehouse_typ SCOPE IS warehouse_table);INSERT INTO warehouse_table VALUES (1, 'Downtown', 99);INSERT INTO location_table SELECT 10, REF(w)FROM warehouse_table w;SELECT REFTOHEX(building) FROM location_table;DROP TABLE warehouse_table PURGE; ROWIDTOCHAR Converts a rowid value to VARCHAR2 datatype ROWIDTOCHAR(rowid); SELECT COUNT(*)FROM servers;SELECT rowidFROM serversWHERE rownum < 11;SELECT ROWIDFROM serversWHERE ROWIDTOCHAR(ROWID) LIKE '%AAB%'; ROWIDTONCHAR Converts a rowid value to NVARCHAR2 datatype ROWIDTOCHAR(rowid) See ROWIDTOCHAR demo above SCN_TO_TIMESTAMP Returns the approximate Timestamp for an SCN SCN_TO_TIMESTAMP(<scn>); SELECT current_scnFROM v$database;SELECT SCN_TO_TIMESTAMP(8215026-250000)FROM dual; TIMESTAMP_TO_SCN Returns the approximate SCN for a timestamp TIMESTAMP_TO_SCN(<timestamp>) SELECT TIMESTAMP_TO_SCN(SYSTIMESTAMP)FROM dual; TO_BINARY_DOUBLE Converts a Value to the BINARY_DOUBLE Data Type TO_BINARY_DOUBLE(<value>); See TO_NUMBER demo, below. TO_BINARY_FLOAT Converts a Value to the BINARY_FLOAT Data Type TO_BINARY_FLOAT(<value>) RETURN BINARY_FLOAT See TO_NUMBER demo, below. TO_CHAR Convert Datatype To String TO_CHAR(<string_or_column>, <format>) RETURN VARCHAR2 SELECT TO_CHAR(SYSDATE, 'MM/DD/YYYY HH:MI:SS') FROM dual; Converts DATE and TIMESTAMP to VARCHAR2 with the specified format The "X" in the ROUND and TRUNC column indicates that these symbols with these functions TO_DATE(<date_string>, <format mask>, <NLS_PARAMETER>) -- before running these demosSQL> ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS'; Symbol Description ROUND TRUNC CC One greater than the first two digits of a four-digit year X X SQL> SELECT TO_CHAR(SYSDATE, 'CC') FROM dual;TO_CHAR(SYSDATE,'CC')---------------------------------------------21 D Starting day of the week X X SQL> SELECT TO_CHAR(SYSDATE, 'D') FROM dual;TO_CHAR(SYSDATE,'D')--------------------------------------------4 DD Day X X SQL> SELECT TO_CHAR(SYSDATE, 'DD') FROM dual;TO_CHAR(SYSDATE,'DD')---------------------------------------------02 DDD Day X X SQL> SELECT TO_CHAR(SYSDATE, 'DDD') FROM dual;TO_CHAR(SYSDATE,'DDD')----------------------------------------------093 DAY Starting day of the week X X SQL> SELECT TO_CHAR(SYSDATE, 'DAY') FROM dual;TO_CHAR(SYSDATE,'DAY')----------------------------------------------WEDNESDAY DY Starting day of the week X X SQL> SELECT TO_CHAR(SYSDATE, 'DY') FROM dual;TO_CHAR(SYSDATE,'DY')----------------------------------------------WED HH Hours X X SQL> SELECT TO_CHAR(SYSDATE, 'HH') FROM dual;TO_CHAR(SYSDATE,'HH')---------------------------------------------10 HH12 Hours SQL> SELECT TO_CHAR(SYSDATE, 'HH12') FROM dual;TO_CHAR(SYSDATE,'HH12')-----------------------------------------------10 HH24 Hours SQL> SELECT TO_CHAR(SYSDATE, 'HH24') FROM dual;TO_CHAR(SYSDATE,'HH24')-----------------------------------------------22 I ISO Year X X SQL> SELECT TO_CHAR(SYSDATE, 'I') FROM dual;TO_CHAR(SYSDATE,'I')--------------------------------------------8 IW Same day of the week as the first day of the ISO year SQL> SELECT TO_CHAR(SYSDATE, 'IW') FROM dual;TO_CHAR(SYSDATE,'IW')---------------------------------------------14 IY ISO Year SQL> SELECT TO_CHAR(SYSDATE, 'IY') FROM dual;TO_CHAR(SYSDATE,'IY')---------------------------------------------08 IYY ISO Year SQL> SELECT TO_CHAR(SYSDATE, 'IYY') FROM dual;TO_CHAR(SYSDATE,'IYY')------------------------------------------------008 IYYY ISO Year SQL> SELECT TO_CHAR(SYSDATE, 'IYYY') FROM dual;TO_CHAR(SYSDATE,'IYYY')------------------------------------------------2008 J Julian Day SQL> SELECT TO_CHAR(SYSDATE, 'J') FROM dual;TO_CHAR(SYSDATE,'J')--------------------------------------------2454559 MI Minutes X X SQL> SELECT TO_CHAR(SYSDATE, 'MI') FROM dual;TO_CHAR(SYSDATE,'MI')---------------------------------------------29 MM Month (rounds up on the sixteenth day) SQL> SELECT TO_CHAR(SYSDATE, 'MM') FROM dual;TO_CHAR(SYSDATE,'MM')---------------------------------------------04 MON Month (rounds up on the sixteenth day) X X SQL> SELECT TO_CHAR(SYSDATE, 'MON') FROM dual;TO_CHAR(SYSDATE,'MON')----------------------------------------------APR MONTH Month (rounds up on the sixteenth day) X X SQL> SELECT TO_CHAR(SYSDATE, 'MONTH') FROM dual;TO_CHAR(SYSDATE,'MONTH')------------------------------------------------APRIL Q Quarter (rounds up on 16th day of the 2nd month of the quarter) SQL> SELECT TO_CHAR(SYSDATE, 'Q') FROM dual;TO_CHAR(SYSDATE,'Q')--------------------------------------------2 RM Month (rounds up on the sixteenth day) in Roman Numerals SQL> SELECT TO_CHAR(SYSDATE, 'RM') FROM dual;TO_CHAR(SYSDATE,'RM')---------------------------------------------IV SCC One greater than the first two digits of a four-digit year X X SQL> SELECT TO_CHAR(SYSDATE, 'SCC') FROM dual;TO_CHAR(SYSDATE,'SCC')----------------------------------------------21 SYYYY Year (rounds up on July 1) X X SQL> SELECT TO_CHAR(SYSDATE, 'SYYYY') FROM dual;TO_CHAR(SYSDATE,'SYYYY')------------------------------------------------2008 W Week number in the month SQL> SELECT TO_CHAR(SYSDATE, 'W') FROM dual;TO_CHAR(SYSDATE,'W')--------------------------------------------1 WW Week of the year SQL> SELECT TO_CHAR(SYSDATE, 'WW') FROM dual;TO_CHAR(SYSDATE,'WW')---------------------------------------------14 Y One Digit Year X X SQL> SELECT TO_CHAR(SYSDATE, 'Y') FROM dual;TO_CHAR(SYSDATE,'Y')--------------------------------------------8 YY Two Digit Year X X SQL> SELECT TO_CHAR(SYSDATE, 'YY') FROM dual;TO_CHAR(SYSDATE,'YY')---------------------------------------------08 YYY Three Digit Year X X SQL> SELECT TO_CHAR(SYSDATE, 'YYY') FROM dual;TO_CHAR(SYSDATE,'YYY')----------------------------------------------008 YYYY Four Digit Year X X SQL> SELECT TO_CHAR(SYSDATE, 'YYYY') FROM dual;TO_CHAR(SYSDATE,'YYYY')-----------------------------------------------2008 CREATE TABLE t (datecol1 DATE,datecol2 DATE);INSERT INTO t (datecol1, datecol2) VALUES (SYSDATE, SYSDATE);col col1 format a30col col2 format a20col col3 format a20col "Financial Quarter" format a20SELECT TO_CHAR(datecol1, 'DAY-MONTH-YY') COL1, TO_CHAR(datecol2, 'D-MM/YYYY HH24:MI:SS') COL2, TO_CHAR(datecol2, 'YYYY-MON-DD HH24') COL3, TO_CHAR(datecol2, 'Q') "Financial Quarter"FROM t; Demo of FM Formatting From Tom Kyte (Oracle Magazine 3-4/2004) SELECT TO_CHAR(dt, 'HH:MI AM') A, TO_CHAR(dt, 'FMHH:MI AM') B, TO_CHAR(dt, 'FMHHFM:MI AM') CFROM (SELECT TO_DATE('09:01 am', 'HH:MI AM') dt FROM dual); Convert NUMBER to CHARACTER TO_CHAR(number) SELECT TO_CHAR(123)FROM dual; Convert NUMBER to HEX TO_CHAR(NUMBER) RETURN HEX SELECT TO_CHAR(1048576,'XXXXXXXX')FROM dual; TO_CLOB Converts CHAR, NCHAR, VARCHAR2, NVARCHAR2, or NCLOB values to CLOB values TO_CLOB(right VARCHAR2 CHARACTER SET ANY_CS) RETURN CLOB; SELECT TO_CLOB('Some value')FROM dual; TO_DATE Convert A String With Default Format To A Date TO_DATE(<string>) RETURN DATE SELECT TO_DATE('01-JAN-2004') FROM dual; Convert A String With A Non-Default Format To A Date TO_DATE(<string>, <format mask>) SELECT TO_DATE('01/01/2004', 'MM/DD/YYYY') FROM dual; Convert A String With A Non-Default Format And Specify The Language TO_DATE(<string>, <format mask>) RETURN DATE SELECT TO_DATE('January 12, 2005, 11:03 A.M.', 'MONTH DD, YYYY, HH:MI A.M.', 'NLS_DATE_LANGUAGE = American')FROM dual; Convert A String With A Non-Default Format And Specify The Language TO_DATE(<date_string>, <format mask>, <NLS_PARAMETER>) RETURN DATE ALTER SESSION SET NLS_TERRITORY = 'JAPAN';SELECT TO_DATE('January 12, 2005, 11:03 A.M.', 'Month dd, YYYY, HH:MI A.M.', 'NLS_DATE_LANGUAGE = American')FROM DUAL;ALTER SESSION SET NLS_TERRITORY = 'AMERICA'; Convert A String To 24 Hour Time TO_DATE(<date_string>, <format mask>) RETURN DATE SELECT TO_CHAR(SYSDATE, 'MM/DD/YY HH24:MI:SS') FROM dual; TO_DSINTERVAL Converts A String To An INTERVAL DAY TO SECOND DataType TO_DSINTERVAL(<date_string>, <format mask>, <NLS_PARAMETER>) conn hr/hrSELECT employee_id, last_name FROM employeesWHERE hire_date + TO_DSINTERVAL('100 10:00:00') <= DATE '1990-01-01'; TO_LOB Converts LONG or LONG RAW values in the column long_column to LOB values TO_LOB(long_column) RETURN LOB desc user_triggersCREATE TABLE lobtest (testcol CLOB);INSERT INTO lobtestSELECT TO_LOB(trigger_body)FROM user_triggers; TO_MULTI_BYTE Returns char with all of its single-byte characters converted to their corresponding multibyte characters TO_MULTI_BYTE(character_string) -- must be run in a UTF8 database to see the differenceSELECT dump('A') FROM dual;SELECT dump(TO_MULTI_BYTE('A')) FROM dual; TO_NCHAR Converts a DATE or TIMESTAMP from the database character set to the National Character Set specified TO_NCHAR(<date_string | interval | CLOB | number>,<format mask>, <NLS_PARAMETER>) RETURN NCHAR SELECT TO_NCHAR('ABC')FROM dual;SELECT TO_NCHAR(1048576)FROM dual;conn oe/oeSELECT TO_NCHAR(order_date)FROM orders WHERE order_status > 9; TO_NCLOB Converts CLOB values in a LOB column or other character strings to NCLOB TO_NCLOB(lob_or_character_value) RETURN NCLOB CREATE TABLE nclob_test(nclobcol NCLOB);desc nclob_testINSERT INTO nclob_test(nclobcol)VALUES(TO_NCLOB('Convert this text into the NCLOB data type')); TO_NUMBER Converts a string to the NUMBER data type TO_NUMBER(<value>[, <format>, <NLS parameter>]) RETURN NUMBER CREATE TABLE test (testcol VARCHAR2(10));INSERT INTO test VALUES ('12345.67');SELECT TO_BINARY_DOUBLE(testcol) BIN_DOUBLE, TO_BINARY_FLOAT(testcol) BIN_FLOAT, TO_NUMBER(testcol) NMBRFROM test; Converts a HEX number to FLOAT TO_NUMBER(<value>, <format>); SELECT TO_NUMBER('0A', 'XX')FROM dual;SELECT TO_NUMBER('1F', 'XX')FROM dual; Converts a HEX number to DECIMAL TO_NUMBER(<binary_float | binary_double | number>,'<hex mask>') RETURN <binary_float | binary_double | number>; SELECT TO_NUMBER(100000,'XXXXXXXX')FROM dual; TO_SINGLE_BYTE Returns char with all of its multibyte characters converted to their corresponding single-byte characters TO_SINGLE_BYTE(character_string) -- must be run in a UTF8 database to see the differenceSELECT TO_SINGLE_BYTE(CHR(15711393))FROM dual; TO_TIMESTAMP Converts a string to an Timestamp Data Type TO_TIMESTAMP(<date_string>, <format mask>, <NLS_PARAMETER>)RETURN TIMESTAMP SELECT TO_TIMESTAMP('2004-12-01 11:00:00','YYYY-MM-DD HH:MI:SS')FROM dual; TO_TIMESTAMP_TZ Converts a string to an Timestamp with Timezone Data Type TO_TIMESTAMP(<date_string>, <format mask>, <NLS_PARAMETER>)RETURN TIMESTAMP WITH TIMEZONE SELECT TO_TIMESTAMP_TZ('2004-12-01 11:00:00 -8:00','YYYY-MM-DD HH:MI:SS TZH:TZM') FROM dual; TO_YMINTERVAL Converts a character string of CHAR, VARCHAR2, NCHAR, or NVARCHAR2 datatype to an INTERVAL YEAR TO MONTH type TO_YMINTERVAL(<char>) RETURN YMINTERVAL SELECT hire_date, hire_date+TO_YMINTERVAL('01-02') "14 months"FROM emp; TRANSLATE USING Converts char into the character set specified for conversions between the database character set and the national character set TRANSLATE(char_string USING <CHAR_CS character_set | NCHAR_CS character set>) conn oe/oeCREATE TABLE translate_tab (char_col VARCHAR2(100),nchar_col NVARCHAR2(50));desc translate_tabINSERT INTO translate_tabSELECT NULL, translated_nameFROM product_descriptionsWHERE product_id = 3501;col char_col format a30col nchar_col format a30SELECT * FROM translate_tab;UPDATE translate_tabSET char_col = TRANSLATE(nchar_col USING CHAR_CS);SELECT * FROM translate_tab; UNISTR Convert String To The National Character Set (either UTF8 or UTF16) UNISTR(ch VARCHAR2 CHARACTER SET ANY_CS) RETURN NVARCHAR2; SELECT UNISTR(ASCIISTR(CHR(128) || 'Hello' || CHR(255)))FROM dual; Related Topics Date Functions Numeric Functions String Functions Timestamp XML Functions
最新做一些基金业绩比较的工作,必不可少的需要用到晨星、银河这两家证监会认可的大佬发布的业绩排行榜。但却存在一个很大的问题,两家公司的榜单格式都是自定义的,没有统一标准,也不是传统的二维表。 为了在此基础上开发的程序比较方便的获取数据,所以用VBA做了如下 《评级报告数据转换.xla》的EXCEL插件,较好的将榜单转换为了传统的二维表,这样不管是直接使用,还是导入数据库都比较方便,特分享与大家,有需要的同学可以下载试用。/Files/heekui/评级报告数据转换.rar 版本适用于: 晨星——晨星开放式基金业绩排行榜(大众版).xls 、晨星封闭式基金业绩排行榜(大众版).xls 银河——中国基金业绩周报.xls 使用方法: 1、打开以上类型的评级报告 2、双击 评级报告数据转换.xla,有提示时,启用宏 3、点击工具栏左上角对应的新增的“晨星评级报告”或“银河评级报告” 4、弹出的对话框中选择保存文件地址和名称,点击确定
项目中遇到一个需求,需要将多行合并为一行。表结构如下:NAME Null Type------------------------ --------- -----N_SEC_CODE NOT NULL CHAR(6)C_RESEARCHER_CODE NOT NULL VARCHAR2(20)此表保存了“股票”与“研究员”的对应关系数据,一般而言,对于同一只股票而言,可能有多个研究员对其进行跟踪研究。所以目前遇到一个要求,需查询出每只股票和对应的研究员(研究员代码间,使用逗号分隔)。例如有如下数据:000297 chenpeng 000297 liusu 合并处理后需显示为:000297 chenpeng,liusu网上查了很多方法,但通常而言都是编写自定义多行文本合并函数,或者对支持的列数具有局限性。最后在英文google中搜到如下比较巧的方法。不用在数据库中增加function,纯SQL一次性搞定,而且扩充性很好,没有列的限制。 Code Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->SELECT n_sec_code, TRANSLATE (LTRIM (text, '/'), '*/', '*,') researcherList FROM (SELECT ROW_NUMBER () OVER (PARTITION BY n_sec_code ORDER BY n_sec_code, lvl DESC) rn, n_sec_code, text FROM (SELECT n_sec_code, LEVEL lvl, SYS_CONNECT_BY_PATH (c_researcher_code,'/') text FROM (SELECT n_sec_code, c_researcher_code as c_researcher_code, ROW_NUMBER () OVER (PARTITION BY n_sec_code ORDER BY n_sec_code,c_researcher_code) x FROM m_researcher_stock_rel ORDER BY n_sec_code, c_researcher_code) a CONNECT BY n_sec_code = PRIOR n_sec_code AND x - 1 = PRIOR x)) WHERE rn = 1ORDER BY n_sec_code; 预想的结果成功出现,多行数据成功汇总到一行,特此分享与大家。对于你自己的应用中,只需要把SQL中“n_sec_code”换为你的用来汇总的列,“c_researcher_code”替换为需合并文本的列,“m_researcher_stock_rel”替换为你的表名,就是这么简单。SQL分析:1、利用 “ROW_NUMBER () OVER (PARTITION BY……” 为按“股票代码”汇总后的数据行添加组内序号2、“SYS_CONNECT_BY_PATH” 按组内序号相邻关系,为每一层进行不同行的“研究员代码”叠加3、再次利用“股票代码”进行组内分组,但按第二部中的层次排倒序,增加调整后等级4、取所有调整后等级为1的结果,即为所要求的数据行方法很巧妙,值得学习。:-)感谢网友@OctoberOne、@ericqliu的指点,在ORACLE10中可使用以下方法:SELECT n_sec_code, wmsys.wm_concat (c_researcher_code) as resultFROM m_researcher_stock_relGROUP BY n_sec_code
最近用.Net新建了一个Webservice,在项目添加Log4Net后,测试状态下一切正常。 但一旦发布网站到IIS以后,发现日志不能正常记录了。屡次失败后,偶然想到,难道是文件夹权限的问题。 于是尝试为此服务文件夹的已验证用户设置修改和写入权限,日志记录OK! 留此备忘。
在过去差不多一个月的时间里,先后看到这样两则新闻: 1、微软新推的搜索引擎网站bing(必应)http://cn.bing.com/,因搜索结果可能包含YY视频内容,而且不需要进入视频所属网站,直接点击即可播放的便利功能。受到互联网管理部门的直接禁止访问的处罚,中文bing网站中止了很多天。 2、谷歌中国的http://www.google.cn,引领搜索时尚的用户输入部分关键字时,得到自动提醒的关键字补充功能。因涉及某些YY关键字自动匹配,以及查询结果中有大量不“河蟹”的内容,也收到了处罚和限期整改的通知。 当然,对于公共关系维持、危机公关的处理上,两大公司都及时采取了措施。微软,清洗了大量不和谐的关键字,同时关闭了视频结果直接播放功能,必须客户到视频发布网站才能观看。谷歌中国,也及时关闭了关键字自动匹配这一便利功能,以及不提供境外网站查询结果。 为什么业界领先的这两大巨头,在同一问题上栽跟头呢?而且都在自主的、引以为豪的技术领域,最终却只有采取“被迫”的技术降级方式来应对问题。 我想起了软件工程里,可行性分析阶段的一项重要工作——“社会可行性”(即政策、法律、社会道德等方面的可行性约束)。在当今中国的和谐环境下,面向公众提供的软件或服务时,社会可行性分析不可忽视。我们不容质疑微软和谷歌的技术实力,诚然从用户体验的角度出发,视频直接播放、关键字自动匹配都是很不错的功能,但如果与实际服务提供地的法律或社会环境相悖时,再好的技术应用,都要三思而后行。可行性分析都过不了的话,后面的设计和实施也不必再继续下去了。 最后,祝 有求“必应”,“谷歌”长久!
昨晚和同事们在酒吧狂欢,回家倒头狂睡之后,睁开朦胧的睡眼,2009年已悄然来到。 好久没为空间写点什么了,枕边放着笔记本,躺在床上,决定为新年的第一天写上一篇。 2008,给我们带来了不少不好的回忆,天灾人祸。 年初的雪灾、西藏事件,刚过去不久,汶川强震又在白天工作时间不期而遇, 当温总在北川中学高三临时教室黑板上写下“多难兴邦”四个大字时,我感受最多的是一种无奈。人类的力量还是那么渺小,在自然的不可抗力来临时,总是苍白无力。作为生活在成都的同志,也和老婆在室外待了诚惶诚恐的两个晚上,并为成都成为“人均拥有帐篷最多的城市”贡献了一份微薄的力量。当然还有之后的毒奶粉事件、贯通全年的股市大跌、年末的金融危机等等。总之,2008成为了记忆中一个难忘的多难之年。 当然也有些在平和之年无上荣光的事件,如奥运成功举办,并勇夺金牌榜第一,神七发射升空,不过相比天灾人祸,这些也只是成为对2008的一些安慰。 2009已经来到,金融危机还没散去,股市仍然在寒冬中等待春天,余震还偶尔的来上一两次。不过新年伊始,总是给人以新的期待,一切都会过去的。 温总题词的后面两字“兴邦”,这个重大责任需要我们大家去完成。还是那句老话,新年新气象,大家加油吧! 2009对于自己的工作、生活也许也会有一个较大的改变,祝福自己能随遇而安,当然肯定少不了亲爱的老婆的鼓励,和朋友、家人们的帮助。祝福大家新年快乐!牛气冲天!2009 犇犇犇!
如果在ORACLE里面用惯了Sequence的兄弟们,要在SqlServer里实现Sequence,就会发现没有现成的Sequence对象可以Create了。那应该怎么办呢? 当然这点小问题是难不倒我们程序员的,“max+1啊”,有人会说这样的方式。是的,这种方式实现起来也比较简单。当然你也许还会说,最Sql的方式是采用identity列,自增的方式去增加就ok了。但是这样的列如果要实现“YYYYMMDD”+Sequence值 (例如:2008072400001)的格式就不行了。还是老老实实用存储过程来取得一个Sequence值吧,使用起来也就随心所欲了。 网上常见的一个存储过程为 为当前库所有用到Sequence建一张表,譬如“AllSequence”,内含四个字段【名字,起点值,递增值,当前值】,创建Sequence的时候就创建一条记录,获取Sequence的时候就从对应行的当前值按递增值增加得到。 在并发性请求不那么高的系统里,这种过程是没有问题的。但是并发性请求一旦处于某个量级以后,这个过程常常会遇到问题。 以下为一个改进方法,适合于高吞吐量的访问请求,比如每秒数千次的请求: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->-- 假定要给T_0101001创建一个Sequence-- 创建表SeqT_0101001create table SeqT_0101001( -- ID列为自增列 SeqID int identity(1,1) primary key, -- Sequence值 SeqVal varchar(1))-- 创建从SeqT_0101001表获取最新Sequence值的存储过程create procedure P_GetNewSeqVal_SeqT_0101001asbegin -- 声明新Sequence值变量 declare @NewSeqValue int -- 设置插入、删除操作后的条数显示取消 set NOCOUNT ON -- 插入新值到SeqT_0101001表 insert into SeqT_0101001 (SeqVal) values ('a') -- 设置新Sequence值为插入到SeqT_0101001表的标识列内的最后一个标识值 set @NewSeqValue = scope_identity() -- 删除SeqT_0101001表(不显示被锁行) delete from SeqT_0101001 WITH (READPAST)-- 返回新Sequence值return @NewSeqValueend--使用SequenceDeclare @NewSeqVal intExec @NewSeqVal = P_GetNewSeqVal_SeqT_0101001Print @NewSeqVal 要获取刚才我们提到的 “20080724000056”这种格式的话,下面这样就可以了 select Convert(char(8),Getdate(),112) + right('00000'+CAST(@NewSeqVal AS varchar(5)),5) as mySeq 不过还是有用的不爽的一点地方,不能直接在非存储过程的select的语句中直接使用。
一、更新: 常会遇到 OleDbException - "标准表达式中数据类型不匹配。"使用 OleDb 向 Access (.mdb) 插入 DateTime 数据时经常触发该异常。 解决办法: 对于日期型字段设置参数类型parameter.OleDbType = OleDbType.Date; 不要使用 DbDate, DbTime, DbTimeStamp。 二、插入: 常会遇到 Insert into 语句不合法 解决办法: 字段名加上[] 。例如:Insert into T1 ( [p1],[p2] ) ……
5.12大地震——谢可欣 小学二年级血肉容容痛在心,救人一命乐开怀。房屋倒塌没了家,众志成城建家园。 帮小妹妹在我的博客里发一个,表示一下她对地震痛苦的看法和重建家园心愿。
GridView自带了数据排序功能。在设计视图下,只能对GridView的排序数据列和排序方向进行静态设置。在后台程序中,则需要用Attributes方式对GridView的这两个属性进行动态设置。 示例如下: (前台) <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server"> <title>无标题页</title></head><body> <form id="form1" runat="server"> <div> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" AllowSorting="True" OnSorting="GridView1_Sorting"> <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> <RowStyle BackColor="#EFF3FB" /> <Columns> <asp:BoundField DataField="id" HeaderText="ID" SortExpression="id" /> <asp:BoundField DataField="name" HeaderText="NAME" SortExpression="name" /> <asp:BoundField DataField="age" HeaderText="AGE" SortExpression="age" /> </Columns> <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" /> <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" /> <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> <EditRowStyle BackColor="#2461BF" /> <AlternatingRowStyle BackColor="White" /> </asp:GridView> </div> </form></body></html> 前台注意点: 需要对GridView启用AllowSorting、设置OnSorting事件,对需要排序的列设定SortExpression属性。 (后台) using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 设定初始排序参数值 // 错误的属性设置方法:SortExpression、SortDirection均是GridView只读属性,无法直接赋值。 //this.GridView1.SortExpression = "id"; //this.GridView1.SortDirection = "ASC"; // 正确的属性设置方法 this.GridView1.Attributes.Add("SortExpression", "id"); this.GridView1.Attributes.Add("SortDirection", "ASC"); // 绑定数据源到GridView this.BindGridView(); } } /// <summary> /// GridView排序事件 /// </summary> protected void GridView1_Sorting(object sender, GridViewSortEventArgs e) { // 从事件参数获取排序数据列 string sortExpression = e.SortExpression.ToString(); // 假定为排序方向为“顺序” string sortDirection = "ASC"; // “ASC”与事件参数获取到的排序方向进行比较,进行GridView排序方向参数的修改 if (sortExpression == this.GridView1.Attributes["SortExpression"]) { //获得下一次的排序状态 sortDirection = (this.GridView1.Attributes["SortDirection"].ToString() == sortDirection ? "DESC" : "ASC"); } // 重新设定GridView排序数据列及排序方向 this.GridView1.Attributes["SortExpression"] = sortExpression; this.GridView1.Attributes["SortDirection"] = sortDirection; this.BindGridView(); } /// <summary> /// 绑定到GridView /// </summary> private void BindGridView() { // 获取GridView排序数据列及排序方向 string sortExpression = this.GridView1.Attributes["SortExpression"]; string sortDirection = this.GridView1.Attributes["SortDirection"]; // 调用业务数据获取方法 DataTable dtBind = this.getDB(); // 根据GridView排序数据列及排序方向设置显示的默认数据视图 if ((!string.IsNullOrEmpty(sortExpression)) && (!string.IsNullOrEmpty(sortDirection))) { dtBind.DefaultView.Sort = string.Format("{0} {1}", sortExpression, sortDirection); } // GridView绑定并显示数据 this.GridView1.DataSource = dtBind; this.GridView1.DataBind(); } /// <summary> /// 获取数据源的方法 /// </summary> /// <returns>数据源</returns> private DataTable getDB() { DataTable dt = new DataTable(); dt.Columns.Add("id"); dt.Columns.Add("name"); dt.Columns.Add("age"); dt.Rows.Add(new object[] { "000001", "hekui", "26" }); dt.Rows.Add(new object[] { "000002", "zhangyu", "26" }); dt.Rows.Add(new object[] { "000003", "zhukundian", "27" }); dt.Rows.Add(new object[] { "000004", "liyang", "25" }); dt.Rows.Add(new object[] { "000005", "caili", "27" }); return dt; } } 示例工程:/Files/heekui/GridViewSort.rar
资料来自:http://www.mozlite.com/Article/sqlserver2005.aspx 以下列出的是SqlServer2005在编程过程中的链接字符串,可用于C++,VC++,ASP,PHP,.NET等等语言中。 SQL Native Client ODBC Driver Standard Security Driver={SQL Native Client};Server=myServerAddress;Database=myDataBase;Uid=myUsername;Pwd=myPassword; Trusted Connection Driver={SQL Native Client};Server=myServerAddress;Database=myDataBase;Trusted_Connection=yes; Connecting to a SQL Server Instance Driver={SQL Native Client};Server=myServerName\theInstanceName;Database=myDataBase;Trusted_Connection=yes; Prompt UserName and Password oConn.Properties("Prompt") = adPromptAlways Driver={SQL Native Client};Server=myServerAddress;Database=myDataBase; Enabling MARS(multiple active results sets) Driver={SQL Native Client};Server=myServerAddress;Database=myDataBase;Trusted_Connection=yes;MARS_Connection=yes; Encrypt data sent over network Driver={SQL Native Client};Server=myServerAddress;Database=myDataBase;Trusted_Connection=yes;Encrypt=yes; Attach a database file on connect to a local SQL Server Express Instance Driver={SQL Native Client};Server=.\SQLExpress;AttachDbFilename=c:\asd\qwe\mydbfile.mdf; Database=dbname;Trusted_Connection=Yes; Attach a database file, located in the data directory, on connect to a local SQL Server Express Instance Driver={SQL Native Client};Server=.\SQLExpress;AttachDbFilename=|DataDirectory|mydbfile.mdf; Database=dbname;Trusted_Connection=Yes; Database Mirroring Data Source=myServerAddress;Failover Partner=myMirrorServer;Initial Catalog=myDataBase;Integrated Security=True; SQL Native Client OLE DB Provider Standard Security Provider=SQLNCLI;Server=myServerAddress;Database=myDataBase;Uid=myUsername;Pwd=myPassword; Trusted Connection Provider=SQLNCLI;Server=myServerAddress;Database=myDataBase;Trusted_Connection=yes; Connecting to a SQL Server Instance Provider=SQLNCLI;Server=myServerName\theInstanceName;Database=myDataBase;Trusted_Connection=yes; Prompt for username and password oConn.Properties("Prompt") = adPromptAlways oConn.Open "Provider=SQLNCLI;Server=myServerAddress;DataBase=myDataBase; Enabling MARS(multiple active results sets) Provider=SQLNCLI;Server=myServerAddress;Database=myDataBase;Trusted_Connection=yes;MarsConn=yes; Encrypt data sent over network Provider=SQLNCLI;Server=myServerAddress;Database=myDataBase;Trusted_Connection=yes;Encrypt=yes; Attach a database file on connect to a local SQL Server Express Instance Provider=SQLNCLI;Server=.\SQLExpress;AttachDbFilename=c:\asd\qwe\mydbfile.mdf; Database=dbname;Trusted_Connection=Yes; Attach a database file,located in the data directory,on connect to a local SQL Server Express Instance Provider=SQLNCLI;Server=.\SQLExpress;AttachDbFilename=|DataDirectory|mydbfile.mdf; Database=dbname;Trusted_Connection=Yes; Database Mirroring Data Source=myServerAddress;Failover Partner=myMirrorServer;Initial Catalog=myDataBase;Integrated Security=True; SqlConnection (.NET) Standard Security Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword; Standard Security alternative syntax Server=myServerAddress;Database=myDataBase;User ID=myUsername;Password=myPassword;Trusted_Connection=False; Trusted Connection Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI; Trusted Connection alternative syntax Server=myServerAddress;Database=myDataBase;Trusted_Connection=True; Connect to a SQL Server Instance Server=myServerName\theInstanceName;Database=myDataBase;Trusted_Connection=True; Trusted connection from a CE device Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI;User ID=myDomain\myUsername;Password=myPassword; Connect via IP address Data Source=190.190.200.100,1433;Network Library=DBMSSOCN;Initial Catalog=myDataBase;User ID=myUsername;Password=myPassword; Enabling MARS(multiple active results sets) Server=myServerAddress;Database=myDataBase;Trusted_Connection=True;MultipleActiveResultSets=true; Attach a database file on connect to a local SQL Server Express Instance Server=.\SQLExpress;AttachDbFilename=c:\asd\qwe\mydbfile.mdf;Database=dbname;Trusted_Connection=Yes; Attach a database file,located in the data directory,on connect to a local SQL Server Express Instance Server=.\SQLExpress;AttachDbFilename=|DataDirectory|mydbfile.mdf; Database=dbname;Trusted_Connection=Yes; Using an user instance on a local SQL Server Express instance Data Source=.\SQLExpress;Integrated Security=true;AttachDbFilename=|DataDirectory|\mydb.mdf;User Instance=true; Database Mirroring Data Source=myServerAddress;Failover Partner=myMirrorServer;Initial Catalog=myDataBase;Integrated Security=True; Asynchronous processing Server=myServerAddress;Database=myDataBase;Integrated Security=True;Asynchronous Processing=True; SQL Server 2005 specials [ context connection ] C#代码 using(SqlConnection connection = new SqlConnection("context connection=true")) { connection.Open(); // Use the connection } Visual Basic代码 Using connection as new SqlConnection("context connection=true") connection.Open() ' Use the connection End Using
工作中我们常常需要加壳(escape)后传输或保存HTML文本,UI层使用时再进行脱壳(unescape)。 很庆幸.net为我们提供了非常好用的HttpUtility类,加壳时可采用HtmlEncode方法,脱壳时采用HtmlDecode。 但实际使用这两个方法时,即可知道HtmlDecode很好很实用;HtmlEncode却显得先天不足,仅能转换很少的一些html标记(如:<), 中文、全角符号或大量的特殊字符根本没有进行转换。因此在传输或保存入库时总会遇到这样那样的问题。 解决这一问题的方法其实很简单,每一个可敲出的字符总是对应了一个Unicode编码,而编码又对应了一个32位的整形数字, 那么使用 {数字}; 的形式就可以转换文本,即HtmlEntities。[关于HtmlEntities可查看:http://www.cnblogs.com/templates/waxdoll/htmlentities.htm]转换的函数: 1 /**//// <summary> 2 /// HTMLEntitiesEncode(HTMLEntities编码) 3 /// </summary> 4 /// <param name="text">需要转换的html文本</param> 5 /// <returns>HTMLEntities编码后的文本</returns> 6 public static string HtmlEntitiesEncode(string text) 7 { 8 // 获取文本字符数组 9 char[] chars = HttpUtility.HtmlEncode(text).ToCharArray();10 11 // 初始化输出结果12 StringBuilder result = new StringBuilder(text.Length + (int)(text.Length * 0.1));1314 foreach (char c in chars)15 {16 // 将指定的 Unicode 字符的值转换为等效的 32 位有符号整数17 int value = Convert.ToInt32(c);1819 // 内码为127以下的字符为标准ASCII编码,不需要转换,否则做 {数字}; 方式转换20 if (value > 127)21 {22 result.AppendFormat("{0};", value);23 }24 else25 {26 result.Append(c);27 }28 }2930 return result.ToString();31 } (使用时记得引入 using System.Text) 测试代码: 1 protected void Button3_Click(object sender, EventArgs e) 2 { 3 // 常规HtmlEncode编码 4 string strHtmlEncode = HttpUtility.HtmlEncode("<tr><td>《sss123┏你好啊┓123®はい》</td></tr>"); 5 6 // 增强的HtmlEntities编码 7 string strHtmlEntitiesEncode = HtmlEntitiesEncode("<tr><td>《sss123┏你好啊┓123®はい》</td></tr>"); 8 9 string strHtmlDecode1 = HttpUtility.HtmlDecode(strHtmlEncode);1011 string strHtmlDecode2 = HttpUtility.HtmlDecode(strHtmlEntitiesEncode);12 } 运行时监视截图: 可以很清楚的看到增强的HtmlEncode方法较完美地转换了中文或一些特殊字符,而且HtmlDecode的结果都是一样的。
很多时候我们需要在GridView的RowCommand之类的事件中需要获取当前行的一些关联性的数据值。但这些数据值又没有直接体现在GridView的列中。这个时候该怎么办呢? 有同学喜欢用隐藏列的方式,把需要使用但不显示的字段绑定到此列上,同时设置列宽为0或不显示,使用时可以用常规的取某行某列的方式来获取数据。 但是在Framework 2.0中,我们可以采用DataKeyNames的方式来获取此类数据。 代码示例: (前台) <asp:GridView ID="GridView1" runat="server" DataKeyNames="Grup" OnRowCommand="GridView1_RowCommand" AutoGenerateColumns="False"> <Columns> <asp:TemplateField> <ItemTemplate> <asp:Label ID="Label1" runat="server" Text='<%#Eval("GrupName") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:ButtonField Text="按钮" /> </Columns> </asp:GridView> Grup 为我们想使用但不需要显示的列。(如果有多个字段,使用逗号分开) (后台) protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack ) { DataTable dt = new DataTable(); dt.Columns.Add("Grup"); dt.Columns.Add("GrupName"); dt.Rows.Add(new object[] { 0,"营业部" }); dt.Rows.Add(new object[] { 1,"市场部" }); this.GridView1.DataSource = dt; this.GridView1.DataBind(); } } protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { // 获取当前行索引 int index = Convert.ToInt32(e.CommandArgument); // 取出当前行数据键值对象中的值 string strGrup = ((GridView)sender).DataKeys[index].Values["Grup"].ToString(); } 顺便补充一句。 如果你使用模板列中放置按钮控件的方式,要想在按钮事件中获取这种字段值就更简单了。 只需要在按钮的CommandArgument属性设置为想绑定的字段,如: <asp:TemplateField> <ItemTemplate> <asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="Button" CommandArgument=' <%#Eval("Grup") %>' /> </ItemTemplate> </asp:TemplateField> 按钮事件中如是写: protected void Button2_Click(object sender, EventArgs e) { string strGrup = ((Button)sender).CommandArgument.ToString(); }
近日的一系列工作是做网站的营运维护,因此做了大量的支持工具。有Excel中写VBA的,也有直接C#做的工具。有时需要在C#中执行Excel VBA宏,甚至有时还需要在执行了VBA宏之后,获取返回值再进行相应的处理。为了使用方便,我写了一个执行Excel VBA宏的帮助类 。放在博客里做个备份也希望对有类似需求的朋友有所帮助。 帮助类仅提供了一个方法:RunExcelMacro参数说明: string excelFilePath Excel文件路径 string macroName 宏名称 object[] parameters 宏参数组 out object rtnValue 宏返回值 bool isShowExcel 执行时是否显示Excel补充说明:VBA宏需如下图写在模块中,才能被此方法识别。写在ThisWorkBook中不能被识别。 执行Excel VBA宏帮助类,注释比较详细,不再累赘代码过程。最核心部分其实就是通过反射方式调用Excel VBA宏,oBook.Save()这句话也很重要,否则即使执行了VBA宏调用,也不会保存Excel更改后的内容: 1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using Excel = Microsoft.Office.Interop.Excel; 5 using Microsoft.Office.Core; 6 using System.IO; 7 8 namespace DoVBAMacro 9 { 10 /// <summary> 11 /// 执行Excel VBA宏帮助类 12 /// </summary> 13 public class ExcelMacroHelper 14 { 15 /// <summary> 16 /// 执行Excel中的宏 17 /// </summary> 18 /// <param name="excelFilePath">Excel文件路径</param> 19 /// <param name="macroName">宏名称</param> 20 /// <param name="parameters">宏参数组</param> 21 /// <param name="rtnValue">宏返回值</param> 22 /// <param name="isShowExcel">执行时是否显示Excel</param> 23 public void RunExcelMacro( 24 string excelFilePath, 25 string macroName, 26 object[] parameters, 27 out object rtnValue, 28 bool isShowExcel 29 ) 30 { 31 try 32 { 33 #region 检查入参 34 35 // 检查文件是否存在 36 if (!File.Exists(excelFilePath)) 37 { 38 throw new System.Exception(excelFilePath + " 文件不存在"); 39 } 40 41 // 检查是否输入宏名称 42 if (string.IsNullOrEmpty(macroName)) 43 { 44 throw new System.Exception("请输入宏的名称"); 45 } 46 47 #endregion 48 49 #region 调用宏处理 50 51 // 准备打开Excel文件时的缺省参数对象 52 object oMissing = System.Reflection.Missing.Value; 53 54 // 根据参数组是否为空,准备参数组对象 55 object[] paraObjects; 56 57 if (parameters == null) 58 { 59 paraObjects = new object[] { macroName }; 60 } 61 else 62 { 63 // 宏参数组长度 64 int paraLength = parameters.Length; 65 66 paraObjects = new object[paraLength + 1]; 67 68 paraObjects[0] = macroName; 69 for (int i = 0; i < paraLength; i++) 70 { 71 paraObjects[i + 1] = parameters[i]; 72 } 73 } 74 75 // 创建Excel对象示例 76 Excel.ApplicationClass oExcel = new Excel.ApplicationClass(); 77 78 // 判断是否要求执行时Excel可见 79 if (isShowExcel) 80 { 81 // 使创建的对象可见 82 oExcel.Visible = true; 83 } 84 85 // 创建Workbooks对象 86 Excel.Workbooks oBooks = oExcel.Workbooks; 87 88 // 创建Workbook对象 89 Excel._Workbook oBook = null; 90 91 // 打开指定的Excel文件 92 oBook = oBooks.Open( 93 excelFilePath, 94 oMissing, 95 oMissing, 96 oMissing, 97 oMissing, 98 oMissing, 99 oMissing,100 oMissing,101 oMissing,102 oMissing,103 oMissing,104 oMissing,105 oMissing,106 oMissing,107 oMissing108 );109 110 // 执行Excel中的宏111 rtnValue = this.RunMacro(oExcel, paraObjects);112 113 // 保存更改114 oBook.Save();115 116 // 退出Workbook117 oBook.Close(false, oMissing, oMissing);118 119 #endregion120 121 #region 释放对象122 123 // 释放Workbook对象124 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);125 oBook = null;126 127 // 释放Workbooks对象128 System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);129 oBooks = null;130 131 // 关闭Excel132 oExcel.Quit();133 134 // 释放Excel对象135 System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);136 oExcel = null;137 138 // 调用垃圾回收139 GC.Collect();140 141 #endregion142 }143 catch (Exception ex)144 {145 throw ex;146 }147 }148 149 /// <summary>150 /// 执行宏151 /// </summary>152 /// <param name="oApp">Excel对象</param>153 /// <param name="oRunArgs">参数(第一个参数为指定宏名称,后面为指定宏的参数值)</param>154 /// <returns>宏返回值</returns>155 private object RunMacro(object oApp, object[] oRunArgs)156 {157 try158 {159 // 声明一个返回对象160 object objRtn;161 162 // 反射方式执行宏163 objRtn = oApp.GetType().InvokeMember(164 "Run",165 System.Reflection.BindingFlags.Default |166 System.Reflection.BindingFlags.InvokeMethod,167 null,168 oApp,169 oRunArgs170 );171 172 // 返回值173 return objRtn;174 175 }176 catch (Exception ex)177 {178 // 如果有底层异常,抛出底层异常179 if (ex.InnerException.Message.ToString().Length > 0)180 {181 throw ex.InnerException;182 }183 else184 {185 throw ex;186 }187 }188 }189 }190 }191 示例三个VBA宏方法: 1 Sub getTime() 2 3 Sheet1.Cells(1, 1) = Now 4 5 End Sub 6 7 8 Sub getTime2(title As String) 9 10 Sheet1.Cells(2, 1) = title & " : " & Now11 12 End Sub13 14 Function getTime3(title As String) As String15 16 getTime3 = title & " : " & Now17 18 End Function19 对应的三个使用方法1 不带参数的宏调用(兼演示执行过程显示Excel文件)2 带参数的宏调用(兼演示执行过程不显示Excel文件)3 有返回值的宏调用 1 private void btnExe_Click(object sender, EventArgs e) 2 { 3 try 4 { 5 // 返回对象 6 object objRtn = new object(); 7 8 // 获得一个ExcelMacroHelper对象 9 ExcelMacroHelper excelMacroHelper = new ExcelMacroHelper();10 11 // 执行指定Excel中的宏,执行时显示Excel12 excelMacroHelper.RunExcelMacro(13 @"E:\csharp_study\DoVBAMacro\test.xls",14 "getTime2",15 new Object[] { "现在时刻" },16 out objRtn,17 true18 );19 20 // 执行指定Excel中的宏,执行时不显示Excel21 excelMacroHelper.RunExcelMacro(22 @"E:\csharp_study\DoVBAMacro\test.xls",23 "getTime2",24 new Object[] { "现在时刻" },25 out objRtn,26 false27 );28 29 // 执行指定Excel中的宏,执行时显示Excel,有返回值30 excelMacroHelper.RunExcelMacro(31 @"E:\csharp_study\DoVBAMacro\test.xls",32 "getTime3",33 new Object[] { "现在时刻" },34 out objRtn,35 true36 );37 38 MessageBox.Show((string)objRtn);39 40 }41 catch(System.Exception ex)42 {43 MessageBox.Show(ex.Message);44 }45 } 帮助类需添加引用:Microsoft Excel 11.0 Object Library 示例工程下载
Webservice客户端使用一个WebMethod时,如果WebMethod内部出现异常,不管异常是系统级异常或者自定义的异常,均会被包装为SoapException类型的异常,返回给客户端。 客户端再使用这种SoapException时,无法直接从异常类的属性中提取直接的业务异常信息。 网上看到有同学是做了一个SoapException的Helper类,利用正则表达式的方式,从SoapException的属性做文法分析,从中提取业务异常信息。可是感觉这种方法不是很.Net,而且是不保险的一种做法,如果是自定义异常之类的,在做文法分析时可能会有隐患。而且不能更好的体现错误号。 仔细研究了SoapException之后,发现它有个detail属性,可以利用这个Xml文档类型的节点实现较好的异常信息封包。 步骤如下: 一、(服务端)建立 SoapException 的封包方法 /// <summary> /// 异常类型 /// </summary> public enum FaultCode { Client = 0, Server = 1 } /// <summary> /// 封装异常为SoapException /// </summary> /// <param name="uri">引发异常的方法uri</param> /// <param name="errorMessage">错误信息</param> /// <param name="errorNumber">错误号</param> /// <param name="errorSource">错误源</param> /// <param name="code">异常类型</param> /// <returns>封装后的SoapException</returns> public SoapException RaiseException( string uri, string errorMessage, string errorNumber, string errorSource, FaultCode code ) { //初始化限定名 XmlQualifiedName faultCodeLocation = null; //异常类型代码转换 switch (code) { case FaultCode.Client: faultCodeLocation = SoapException.ClientFaultCode; break; case FaultCode.Server: faultCodeLocation = SoapException.ServerFaultCode; break; } //构建异常信息结构体 string strXmlOut = @"<detail>" + "<Error>" + "<ErrorNumber>" + errorNumber + "</ErrorNumber>" + "<ErrorMessage>" + errorMessage + "</ErrorMessage>" + "<ErrorSource>" + errorSource + "</ErrorSource>" + "</Error>" + "</detail>"; //装载为Xml文档 XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(strXmlOut); //实例化SoapException SoapException soapEx = new SoapException(errorMessage, faultCodeLocation, uri, xmlDoc.DocumentElement); //返回SoapException return soapEx; } 二、(服务端)WebMethod的异常处理中调用此方法。例如: /// <summary> /// 根据ID读取人员信息 /// </summary> /// <returns>人员信息类</returns> [WebMethod(Description = "根据ID读取人员信息")] public PersonInfo WSReadPersonByID(int ID) { try { PersonMethod personMethod = new PersonMethod(); return personMethod.ReadPersonByID(ID); } catch (System.Exception ex) { throw RaiseException( "WSReadPersonByID", ex.Message, "1000", ex.Source, FaultCode.Server ); } } 三、(客户端)建立SoapException的信息解析类 using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using System.Xml;using System.Web.Services.Protocols;/// <summary>/// SoapException 信息解析类/// </summary>public class SoapExceptionInfo { /// <summary> /// 错误号 /// </summary> public string ErrorNumber = string.Empty; /// <summary> /// 错误信息 /// </summary> public string ErrorMessage = string.Empty; /// <summary> /// 错误源 /// </summary> public string ErrorSource = string.Empty; /// <summary> /// SoapExceptionInfo构造方法 /// </summary> public SoapExceptionInfo() { } /// <summary> /// SoapExceptionInfo构造方法 /// </summary> /// <param name="soapEx">SoapException</param> public SoapExceptionInfo(SoapException soapEx) { XmlDocument doc = new XmlDocument(); doc.LoadXml(soapEx.Detail.OuterXml); XmlNode categoryNode = doc.DocumentElement.SelectSingleNode("Error"); this.ErrorNumber = categoryNode.SelectSingleNode("ErrorNumber").InnerText; this.ErrorMessage = categoryNode.SelectSingleNode("ErrorMessage").InnerText; this.ErrorSource = categoryNode.SelectSingleNode("ErrorSource").InnerText; } } 四、(客户端)使用WebMethod时,使用 SoapException的信息解析类方法 public PersonInfo ReadByID(int id) { try { WSDemoService ws = new WSDemoService(); ws.Credentials = System.Net.CredentialCache.DefaultCredentials; return ws.WSReadPersonByID(id); } catch (SoapException soapEx) { SoapExceptionInfo soapExInfo = new SoapExceptionInfo(soapEx); throw new System.Exception(soapExInfo.ErrorMessage); } catch (Exception ex) { throw ex; } }
update某个表时,如果需要和其他表关联,这样的SQL语句在ORACLE中实现起来比较呕心。各个where条件需要分别与一堆select语句嵌套使用才可,晕~~ 以下sql语句是在工作中写出的,做个备忘录: -- 更新应收账款净额update t_0303009 t1 set t1.item_value = (select t2.item_value from ( SELECT a.product_id, a.item_id, b.item_value FROM (SELECT product_id, item_id, item_value FROM t_0303009 WHERE item_id LIKE 'B%011') a, (SELECT product_id, item_id, item_value FROM t_0303009 WHERE item_id LIKE 'B%008') b WHERE a.product_id = b.product_id AND SUBSTR (a.item_id, 2, 6) = SUBSTR (b.item_id, 2, 6) AND a.item_value = 0 ) t2where t1.product_id = t2.product_id and t1.item_id = t2.item_id)where t1.product_id = ( select product_id from ( SELECT a.product_id, a.item_id, b.item_value FROM (SELECT product_id, item_id, item_value FROM t_0303009 WHERE item_id LIKE 'B%011') a, (SELECT product_id, item_id, item_value FROM t_0303009 WHERE item_id LIKE 'B%008') b WHERE a.product_id = b.product_id AND SUBSTR (a.item_id, 2, 6) = SUBSTR (b.item_id, 2, 6) AND a.item_value = 0 ) jj where t1.product_id = jj.product_id and t1.item_id = jj.item_id )and t1.item_id = ( select item_id from ( SELECT a.product_id, a.item_id, b.item_value FROM (SELECT product_id, item_id, item_value FROM t_0303009 WHERE item_id LIKE 'B%011') a, (SELECT product_id, item_id, item_value FROM t_0303009 WHERE item_id LIKE 'B%008') b WHERE a.product_id = b.product_id AND SUBSTR (a.item_id, 2, 6) = SUBSTR (b.item_id, 2, 6) AND a.item_value = 0 ) jj2 where t1.product_id = jj2.product_id and t1.item_id = jj2.item_id )
1、创建测试工程 2、创建测试CASE 3、创建测试列表,并拖动测试CASE到测试列表 4、测试运行测试——代码覆盖率——勾选要测试的项目 5、运行测试 6、查看代码覆盖率结果
项目中我们继承.net系统异常类做成了一个自定义的异常类:WPSYSException在实际程序中发现异常情况时,需要构造并抛出此类异常时,代码如下: //如果输入数组为空,报异常 if ((inDoubleArray == null) || (inDoubleArray.Length == 0)) { //抛出异常 throw new WPSYSException( null, null, ProgID, strErrPos, "输入数组为空", "申请的错误号常量" ); } 使用Vs2005作单元测试时,测试代码应写为以下方式,方可测试程序抛出的异常是否正确: /// <summary> ///ToOneArray (double[]) 的测试(输入数组为空) ///</summary> [TestMethod()] [ExpectedException(typeof(WPSYSException), "输入数组为空")] public void ToOneArrayTest_e1() { double[] inDoubleArray = null; double[] expected = null; double[] actual; actual = WP.SEV001.COM.SYS.S000C11006.ToOneArray(inDoubleArray); } 即,注意在测试方法头加上次属性[ExpectedException(typeof(WPSYSException), "输入数组为空")]WPSYSException:自定义异常类输入数组为空:异常中的信息 ExpectedExceptionAttribute (Type, String) 用预期的异常类型以及描述此异常的消息来初始化 ExpectedExceptionAttribute 类的新实例。 因WPSYSException为自定义的异常类,所在在测试工程中需要引用包含次异常类的dll或者加入代码 此前用以下方式也可实现指定错误信息的正确性测试,但不如上述方法规范: /// <summary> ///ToOneArray (double[]) 的测试(输入数组为空) ///</summary> [TestMethod()] public void ToOneArrayTest_e1() { double[] inDoubleArray = null; double[] expected = null; double[] actual; string strErrorInfo = "输入数组为空"; try { actual = DoubleArrayToOne.ToOne.ToOneArray(inDoubleArray); } catch (System.Exception ex) { Assert.AreEqual(ex.Message, strErrorInfo); } }
做一个2个数据库间数据比较工具时遇到ORACLE中汉字排序的问题。 使用一下SQL select * from T_0303003 order by stock_holder 进行选取数据时(stock_holder为存放中文的字段),结果发现两库返回的记录顺序不一致。琢磨之后应该为字符集问题,一个库字符集为系统默认字符集,另一个库为UTF-8字符集。查找资料后发现,对于中文字段的排序,应该使用以下方式: -- 按拼音排序 (系统默认)select * from T_0303003 order by nlssort(stock_holder,'NLS_SORT=SCHINESE_PINYIN_M');-- 按部首排序 select * from T_0303003 order by nlssort(stock_holder,'NLS_SORT=SCHINESE_RADICAL_M');-- 按笔画排序 select * from T_0303003 order by nlssort(stock_holder,'NLS_SORT=SCHINESE_STROKE_M'); ORACL官方论坛讨论:http://www.oracle-database.cn/oracle_database_It-english-database-0-251288.htmlHave found a strange question recently, arrange in an order Chinese character order by in oracle, " crocodile's word has been ranked at the end to appear! Whether there is such a situation to know the greater part. Whether it is bug i ----------------------------------------------------------- NLS _ SORT? ?? answer2: 1 perhaps this word is many sound words. 2 says and says according to what way you want to arrange in an order. ans wer3: ----------------------------------------------------------- arranges in an order according to the spelling, should need to set up NLS _ SORT. Have Still in test test finish tell and then you body. answer4: ----------------------------------------------------------- O In RACLE, arrange in an order question 1. //Arrange in an order 2 according to the stroke. select * from dept order by nlssort(name,NLS _ SORT =SCHINESE _ STROKE _ M); 3.//Press Take the radical and arrange in an order 4. select * from dept order by nlssort(name,NLS _ SORT =SCHINESE _ RADICAL _ M); 5.//Arrange in an order according to the spelling, this arranges in an order the side for systematic acquiescenc Formula 6. select * from dept order by nlssort(name,NLS _ SORT =SCHINESE _ PINYIN _ M); Can revise NLS _ SORT parameter
昨天受令用VBA做个工具,查看我们项目数据库中某些分析结果表的数据,当然要结合主表之类的形式展现出来。 数据库为ORACLE 9i,因此选用了ADO方式,访问提供器采用了安装ORACLE客户端后自带的Provider Oracle for OLEDB。 刚开始几个表查询数据库数量较少,处理也简单,倒也没什么问题。可是在进行几个大数据量表查询时,总是出现突然关闭EXCEL,或者莫名其妙的问题。最初怀疑是自己程序的问题,断点跟踪后,也看不出个究竟,不过总是在执行查询结果集的时候出现问题。而且问题的出现是偶然、报错内容也有好几样。 实在被它打败了。午饭后,脑筋要活跃一些,想到换一下访问提供器。改为Microsof OLE DB For Oracle.程序其他保持不变。测试n次,没有出现任何异常。:-) 终于搞定了。 怀疑Provider Oracle for OLE DB与微软某些产品的兼容性不够好,例如EXCEL。以后VBA中使用数据库链接时,需考虑这个问题。顺便给大家提个醒。
现象: C#程序中需要以Provider=OraOLEDB.Oracle.1方式访问ORACLE数据库。但程序执行时报异常:未在本地计算机注册“OraOLEDB.Oracle.1”提供程序 解决: 服务器ORACLE为10g,虽然安装时选择了Oracle Data Provider for .net 和Oracle Provider for OLE DB。但是还是需要人工命令行注册一下regsvr32 D:\oracle\10.2.0\db\BIN\OraOLEDB10.dll 原因分析: 也许是因为ORACLE 10g下的dll名字发生了变化。以前叫OraOLEDB.dll
用VBA做工具的过程中,遇见这样一个问题。使用FSO方式或者直接OPEN文件方式,生成的文本文件采用的字符集为当前操作系统默认字符集,不能选择字符集类型。这样的文件作为应用程序的配置文件或者作为js代码文件,常常会因为字符集不是UTF-8,不能直接使用,需要利用记事本进行一次人工的字符集转换。特别麻烦。 近日发现有一办法,可以较好的解决这个问题。即是采用ADO的方式,将字符串生成以指定字符集的流文件输出。 函数代码如下,VB或VBA中均可用。注意:需要添加对ADO 对象库的引用。ADO方式写入 '功能:text保存为文件(ADO方式)'输入:输出文件地址、内容文本、字符集'输出:无Sub WriteToTextFileADO(filePath As String, strContent As String, CharSet As String) Set stm = New ADODB.Stream stm.Type = 2 '以本模式读取 stm.Mode = 3 stm.CharSet = CharSet stm.Open stm.WriteText strContent '如果文件存在,删除文件 If Len(Dir(filePath)) > 0 Then Kill filePath End If stm.SaveToFile filePath, 2 stm.Flush stm.Close Set stm = NothingEnd Sub 使用示例: Call WriteToTextFileADO(Sheets("channel-list").Cells(3, 5) & "\" & feedName & ".xml", feedXml, "utf-8") ADO方式读取 '功能:读取text文件(ADO方式)'输入:输入文件地址、字符集'输出:无Function ReadFromFileADO(filePath As String, CharSet As String) As String Dim strRtn As String Set stm = New ADODB.Stream stm.Type = 2 '以本模式读取 stm.Mode = 3 stm.CharSet = CharSet stm.Open stm.LoadFromFile filePath strRtn = stm.ReadText stm.Close Set stm = Nothing ReadFromFileADO = strRtnEnd Function
下午检查一段SQL时,发现获取最新数据时,可以采用两种方式的SQL写法:1、取记录后按日期逆序后取ROWNUM=1,2、对表的日期取MAX,再和原表关联,取出最大日期对应的数据。为了验证效率,做了以下实验。 数据量: SELECT COUNT(*) FROM GPRXSJB WHERE GPDM = '000001' AND FSRQ < TO_DATE('2007-9-11','YYYY-MM-DD') 结果为 4054行 SQL1(ROWNUM方式): SELECT * FROM ( SELECT SPJ FROM GPRXSJB WHERE GPDM = '000001' AND FSRQ < TO_DATE('2007-9-11','YYYY-MM-DD') ORDER BY FSRQ DESC ) WHERE ROWNUM = 1; 执行平均时间为:7.8 s SQL2(MAX方式): SELECT * FROM GPRXSJB A, ( SELECT MAX(FSRQ) AS MAXDATE FROM GPRXSJB WHERE GPDM = '000001' AND FSRQ < TO_DATE('2007-9-11','YYYY-MM-DD') ) B WHERE A.GPDM = '000001' AND A.FSRQ = B.MAXDATE 执行平均时间为:16 s 效率比较明细第一种要快得多。 可能原因分析: 按第二种方式,与原表关联的笛卡尔积维度较大,所以执行缓慢。 愿牛人们帮忙分析一下,谢谢。
ASP.NET 2.0中CSS失效的问题总结 经常有人遇到ASP.NET 2.0(ASP.NET 1.x中可能是有效的)中CSS失效的问题,现将主要原因和解决方法罗列如下: 1,CSS文件路径不正确 这个问题属于Web开发中的基础问题,一般采用相对路径会出现这样的问题,或者样式文件写在了母版页里面,在内容页与母版页不在同一级目录下时会出现这样的问题。此时你要清楚Web中相对路径的规则,如果你不清楚,可以采用绝对路径的写法试试就知道是不是路径的问题了。 2,CSS规则写法错误 这个问题谁也帮不你,只能自己学习CSS的相关知识了。 3,文件编码问题 有时候,CSS样式放在aspx文件里有效,而放在独立的文件中无效,这样的问题如果不是路径问题,则就是编码问题造成的,可以将CSS文件用记事本打开,再另存为ANSI格式或者UTF-8格式即可。 4,权限问题 这种情况常见的现象是登录之前样式无效,登录之后才有效,这是典型的权限问题造成的。由于web.config配置了所有文件不允许匿名访问,才会出现这样的问题,解决方法就是将<location>标记将样式文件配置为允许匿名访问。例如: <configuration> <location path="允许匿名访问的文件夹名称或者文件路径"> <system.web> <authorization> <allow users="?"/> </authorization> </system.web> </location></configuration> 5,单击按钮样式失效这种情况最典型的原因是单击按钮事件里有类似Response.Write这样的语句,由于ASP.NET 2.0默认采用http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd文档类型定义,它就要求在<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">的前面不能有任何输出。这种问题的解决方法是采用ClientScriptManager输出,或者采用Literal控件输出内容。 6,在ASP.NET 1.x里面起作用的样式到ASP.NET 2.0里面失效 这种问题一般仍然是xhtml1造成的,由于http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd的样式规则与以前的不同,如要加单位,例如width:200;现在要写成width:200px;这种问题的解决方法就是要明确加上单位。 7,脚本设置的样式无效由于xhtml1.DTD要求有单位,因此在设置对象样式的数值时,仍然要加上单位,如obj.style.width = "200px"。下面的代码在Firefox了是无效的(不要抱怨Firefox麻烦) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <script type="text/javascript"> //<![CDATA[ function SetHeight() { document.getElementById("x").style.height="200" } //]]> </script></head><body><div id="x" style="background:#DDD;height:auto;">测试</div><input type="button" value="设置" onclick="SetHeight()" /></body></html> 尽管上面在IE中正常,但在Firefox里面则会出现问题。正确写法为 document.getElementById("x").style.height="200px" Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1760521
很多时候不想写一些心情上的事了,单是一些技术上的觉悟、技巧之类的随笔。 老婆也在问我:怎么不像以前那样常写些东西了呢。我的解释是:在郁闷的时候、心情不好的时候才会有更多的感悟,如果开心了,生活优越了,让我感动的事也就越来越少。 主观上的因素加上客观上的日复一日地加班,也就没有更多的时间静下心来思考些问题。很晚回到家时,小玩一会儿,已经进入深夜了。收拾完毕,躺在床上时,老婆也不在身边,自己随意地翻上几页书,常常灯也忘记关闭,便沉睡而去。一觉醒来时,天已大亮,一番忙碌,看上去类似的新的一天又开始了。好不容易到了周末,常常在周日还会伴随着一日加班。当然从节省家里空调电费的角度而言,无疑去办公室待着要节约不少电费,还能小赚一点加班费。 从实而言,2007前半年的工作上干得也不是很顺心,自己的经验不足,但却委以重任。设计上出现不少漏洞。规范性、执行力上也做得不够。尽管整个项目组都存在这样那样的问题,但我的内疚感,一直围绕着我。成长是要付出代价的,但希望这个代价不会太大。 当生活进入了死循环,便需要一个终止循环的条件。这个条件是什么呢?或许正是下个月老婆的归来。强烈地期待着,老婆,我爱你,请赐予我力量吧!
在访问Formview模板内控件时遇到两个问题。 一是调用语句过早而访问不到Formview模板内控件,二是究竟用什么方法或属性来访问。 比如说其中有一个ID为UserNameTextBox的TextBox,我们要把当前已登陆用户的用户名传给它怎么做呢? 注意:formview在Page_Load的时候是不会呈现外观的,也就不会有TextBox了,所以在Page_Load里写程序无论怎么写也找不到formview1控件模板里的子控件UserNameTextBox。也就是说要等formview控件的外观呈现后才可以找里面的子控件。 这里要用到OnItemCreated事件(FormView_ItemCreated)。 (1)在FormView的属性代码里添加事件: OnItemCreated="FormView_ItemCreated" (或者在属性面板-事件里添加) (2)在当前页CS文件里添加处理程序: protected void FormView_ItemCreated(object sender, EventArgs e) { ((TextBox)FormView1.Row.FindControl("UserNameTextBox")).Text = HttpContext.Current.User.Identity.Name; } //这里FormView的ID为FormView1,模板里有TextBox子控件ID为UserNameTextBox, //HttpContext.Current.User.Identity.Name是取得当前登陆用户的用户名 //((TextBox)FormView1.Row.FindControl("UserNameTextBox")).Text 这句是关键,就是这样访问模板里子控件的。来自:http://hi.baidu.com/txlongping/blog/item/0dd11e1fbe1ececaa6866911.html
今天有朋友请教在CS的WinForm中如何打印DataGridView中的内容。 网上搜索一番之后,还是在藏宝库CodeProject中找到一篇好文章《DataGridView Printing by Selecting Columns and Rows》(http://www.codeproject.com/KB/grid/PrintDataGrid_CS.aspx)效果图 【打印设置画面】 【打印预览画面】解决方案构成 这个打印解决方案由一个打印设置的窗体,及一个打印类组成。 可用于以下场景: 1、显示的数据量较大,但又没有必要打印全部数据的时候 2、希望打印出的列宽能自动适应页面宽度打印类主要方法Print_DataGridView(共有): 被外部类调用的主方法. PrintDoc_BeginPrint(私有): 初始化一些打印变量 PrintDoc_PrintPage(私有): 执行打印工作 DrawFooter(私有): 页脚的处理部分 打印类代码 /**//* *************************************************** * DataGridView打印类 * 原作者:Afrasiab Cheraghi. * 修改者:何奎 * * **************************************************/using System;using System.Collections.Generic;using System.Windows.Forms;using System.Drawing;using System.Collections;using System.Data;using System.Text;namespace testPrint{ class PrintDGV { private static StringFormat StrFormat; // Holds content of a TextBox Cell to write by DrawString private static StringFormat StrFormatComboBox; // Holds content of a Boolean Cell to write by DrawImage private static Button CellButton; // Holds the Contents of Button Cell private static CheckBox CellCheckBox; // Holds the Contents of CheckBox Cell private static ComboBox CellComboBox; // Holds the Contents of ComboBox Cell private static int TotalWidth; // Summation of Columns widths private static int RowPos; // Position of currently printing row private static bool NewPage; // Indicates if a new page reached private static int PageNo; // Number of pages to print private static ArrayList ColumnLefts = new ArrayList(); // Left Coordinate of Columns private static ArrayList ColumnWidths = new ArrayList(); // Width of Columns private static ArrayList ColumnTypes = new ArrayList(); // DataType of Columns private static int CellHeight; // Height of DataGrid Cell private static int RowsPerPage; // Number of Rows per Page private static System.Drawing.Printing.PrintDocument printDoc = new System.Drawing.Printing.PrintDocument(); // PrintDocumnet Object used for printing private static string PrintTitle = ""; // Header of pages private static DataGridView dgv; // Holds DataGridView Object to print its contents private static List<string> SelectedColumns = new List<string>(); // The Columns Selected by user to print. private static List<string> AvailableColumns = new List<string>(); // All Columns avaiable in DataGrid private static bool PrintAllRows = true; // True = print all rows, False = print selected rows private static bool FitToPageWidth = true; // True = Fits selected columns to page width , False = Print columns as showed private static int HeaderHeight = 0; public static void Print_DataGridView(DataGridView dgv1) { PrintPreviewDialog ppvw; try { // Getting DataGridView object to print dgv = dgv1; // Getting all Coulmns Names in the DataGridView AvailableColumns.Clear(); foreach (DataGridViewColumn c in dgv.Columns) { if (!c.Visible) continue; AvailableColumns.Add(c.HeaderText); } // Showing the PrintOption Form PrintOptions dlg = new PrintOptions(AvailableColumns); if (dlg.ShowDialog() != DialogResult.OK) return; PrintTitle = dlg.PrintTitle; PrintAllRows = dlg.PrintAllRows; FitToPageWidth = dlg.FitToPageWidth; SelectedColumns = dlg.GetSelectedColumns(); RowsPerPage = 0; ppvw = new PrintPreviewDialog(); ppvw.Document = printDoc; // Showing the Print Preview Page printDoc.BeginPrint +=new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint); printDoc.PrintPage +=new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage); if (ppvw.ShowDialog() != DialogResult.OK) { printDoc.BeginPrint -= new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint); printDoc.PrintPage -= new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage); return; } // Printing the Documnet printDoc.Print(); printDoc.BeginPrint -= new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint); printDoc.PrintPage -= new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { } } private static void PrintDoc_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e) { try { // Formatting the Content of Text Cell to print StrFormat = new StringFormat(); StrFormat.Alignment = StringAlignment.Near; StrFormat.LineAlignment = StringAlignment.Center; StrFormat.Trimming = StringTrimming.EllipsisCharacter; // Formatting the Content of Combo Cells to print StrFormatComboBox = new StringFormat(); StrFormatComboBox.LineAlignment = StringAlignment.Center; StrFormatComboBox.FormatFlags = StringFormatFlags.NoWrap; StrFormatComboBox.Trimming = StringTrimming.EllipsisCharacter; ColumnLefts.Clear(); ColumnWidths.Clear(); ColumnTypes.Clear(); CellHeight = 0; RowsPerPage = 0; // For various column types CellButton = new Button(); CellCheckBox = new CheckBox(); CellComboBox = new ComboBox(); // Calculating Total Widths TotalWidth = 0; foreach (DataGridViewColumn GridCol in dgv.Columns) { if (!GridCol.Visible) continue; if (!PrintDGV.SelectedColumns.Contains(GridCol.HeaderText)) continue; TotalWidth += GridCol.Width; } PageNo = 1; NewPage = true; RowPos = 0; } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private static void PrintDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { int tmpWidth, i; int tmpTop = e.MarginBounds.Top; int tmpLeft = e.MarginBounds.Left; try { // Before starting first page, it saves Width & Height of Headers and CoulmnType if (PageNo == 1) { foreach (DataGridViewColumn GridCol in dgv.Columns) { if (!GridCol.Visible) continue; // Skip if the current column not selected if (!PrintDGV.SelectedColumns.Contains(GridCol.HeaderText)) continue; // Detemining whether the columns are fitted to page or not. if (FitToPageWidth) tmpWidth = (int)(Math.Floor((double)((double)GridCol.Width / (double)TotalWidth * (double)TotalWidth * ((double)e.MarginBounds.Width / (double)TotalWidth)))); else tmpWidth = GridCol.Width; HeaderHeight = (int)(e.Graphics.MeasureString(GridCol.HeaderText, GridCol.InheritedStyle.Font, tmpWidth).Height) + 11; // Save width & height of headres and ColumnType ColumnLefts.Add(tmpLeft); ColumnWidths.Add(tmpWidth); ColumnTypes.Add(GridCol.GetType()); tmpLeft += tmpWidth; } } // Printing Current Page, Row by Row while (RowPos <= dgv.Rows.Count - 1) { DataGridViewRow GridRow = dgv.Rows[RowPos]; if (GridRow.IsNewRow || (!PrintAllRows && !GridRow.Selected)) { RowPos++; continue; } CellHeight = GridRow.Height; if (tmpTop + CellHeight >= e.MarginBounds.Height + e.MarginBounds.Top) { DrawFooter(e, RowsPerPage); NewPage = true; PageNo++; e.HasMorePages = true; return; } else { if (NewPage) { // Draw Header e.Graphics.DrawString(PrintTitle, new Font(dgv.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Top - e.Graphics.MeasureString(PrintTitle, new Font(dgv.Font, FontStyle.Bold), e.MarginBounds.Width).Height - 13); String s = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString(); e.Graphics.DrawString(s, new Font(dgv.Font, FontStyle.Bold), Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(s, new Font(dgv.Font, FontStyle.Bold), e.MarginBounds.Width).Width), e.MarginBounds.Top - e.Graphics.MeasureString(PrintTitle, new Font(new Font(dgv.Font, FontStyle.Bold), FontStyle.Bold), e.MarginBounds.Width).Height - 13); // Draw Columns tmpTop = e.MarginBounds.Top; i = 0; foreach (DataGridViewColumn GridCol in dgv.Columns) { if (!GridCol.Visible) continue; if (!PrintDGV.SelectedColumns.Contains(GridCol.HeaderText)) continue; e.Graphics.FillRectangle(new SolidBrush(Color.LightGray), new Rectangle((int) ColumnLefts[i], tmpTop, (int)ColumnWidths[i], HeaderHeight)); e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int) ColumnLefts[i], tmpTop, (int)ColumnWidths[i], HeaderHeight)); e.Graphics.DrawString(GridCol.HeaderText, GridCol.InheritedStyle.Font, new SolidBrush(GridCol.InheritedStyle.ForeColor), new RectangleF((int)ColumnLefts[i], tmpTop, (int)ColumnWidths[i], HeaderHeight), StrFormat); i++; } NewPage = false; tmpTop += HeaderHeight; } // Draw Columns Contents i = 0; foreach (DataGridViewCell Cel in GridRow.Cells) { if (!Cel.OwningColumn.Visible) continue; if (!SelectedColumns.Contains(Cel.OwningColumn.HeaderText)) continue; // For the TextBox Column if (((Type) ColumnTypes[i]).Name == "DataGridViewTextBoxColumn" || ((Type) ColumnTypes[i]).Name == "DataGridViewLinkColumn") { e.Graphics.DrawString(Cel.Value.ToString(), Cel.InheritedStyle.Font, new SolidBrush(Cel.InheritedStyle.ForeColor), new RectangleF((int)ColumnLefts[i], (float)tmpTop, (int)ColumnWidths[i], (float)CellHeight), StrFormat); } // For the Button Column else if (((Type) ColumnTypes[i]).Name == "DataGridViewButtonColumn") { CellButton.Text = Cel.Value.ToString(); CellButton.Size = new Size((int)ColumnWidths[i], CellHeight); Bitmap bmp =new Bitmap(CellButton.Width, CellButton.Height); CellButton.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height)); e.Graphics.DrawImage(bmp, new Point((int)ColumnLefts[i], tmpTop)); } // For the CheckBox Column else if (((Type) ColumnTypes[i]).Name == "DataGridViewCheckBoxColumn") { CellCheckBox.Size = new Size(14, 14); CellCheckBox.Checked = (bool)Cel.Value; Bitmap bmp = new Bitmap((int)ColumnWidths[i], CellHeight); Graphics tmpGraphics = Graphics.FromImage(bmp); tmpGraphics.FillRectangle(Brushes.White, new Rectangle(0, 0, bmp.Width, bmp.Height)); CellCheckBox.DrawToBitmap(bmp, new Rectangle((int)((bmp.Width - CellCheckBox.Width) / 2), (int)((bmp.Height - CellCheckBox.Height) / 2), CellCheckBox.Width, CellCheckBox.Height)); e.Graphics.DrawImage(bmp, new Point((int)ColumnLefts[i], tmpTop)); } // For the ComboBox Column else if (((Type) ColumnTypes[i]).Name == "DataGridViewComboBoxColumn") { CellComboBox.Size = new Size((int)ColumnWidths[i], CellHeight); Bitmap bmp = new Bitmap(CellComboBox.Width, CellComboBox.Height); CellComboBox.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height)); e.Graphics.DrawImage(bmp, new Point((int)ColumnLefts[i], tmpTop)); e.Graphics.DrawString(Cel.Value.ToString(), Cel.InheritedStyle.Font, new SolidBrush(Cel.InheritedStyle.ForeColor), new RectangleF((int)ColumnLefts[i] + 1, tmpTop, (int)ColumnWidths[i] - 16, CellHeight), StrFormatComboBox); } // For the Image Column else if (((Type) ColumnTypes[i]).Name == "DataGridViewImageColumn") { Rectangle CelSize = new Rectangle((int)ColumnLefts[i], tmpTop, (int)ColumnWidths[i], CellHeight); Size ImgSize = ((Image)(Cel.FormattedValue)).Size; e.Graphics.DrawImage((Image)Cel.FormattedValue, new Rectangle((int)ColumnLefts[i] + (int)((CelSize.Width - ImgSize.Width) / 2), tmpTop + (int)((CelSize.Height - ImgSize.Height) / 2), ((Image)(Cel.FormattedValue)).Width, ((Image)(Cel.FormattedValue)).Height)); } // Drawing Cells Borders e.Graphics.DrawRectangle(Pens.Black, new Rectangle((int)ColumnLefts[i], tmpTop, (int)ColumnWidths[i], CellHeight)); i++; } tmpTop += CellHeight; } RowPos++; // For the first page it calculates Rows per Page if (PageNo == 1) RowsPerPage++; } if (RowsPerPage == 0) return; // Write Footer (Page Number) DrawFooter(e, RowsPerPage); e.HasMorePages = false; } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private static void DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, int RowsPerPage) { double cnt = 0; // Detemining rows number to print if (PrintAllRows) { if (dgv.Rows[dgv.Rows.Count - 1].IsNewRow) cnt = dgv.Rows.Count - 2; // When the DataGridView doesn't allow adding rows else cnt = dgv.Rows.Count - 1; // When the DataGridView allows adding rows } else cnt = dgv.SelectedRows.Count; // Writing the Page Number on the Bottom of Page string PageNum = " 第 " + PageNo.ToString() + " 页,共 " + Math.Ceiling((double)(cnt / RowsPerPage)).ToString() + " 页"; e.Graphics.DrawString(PageNum, dgv.Font, Brushes.Black, e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(PageNum, dgv.Font, e.MarginBounds.Width).Width) / 2, e.MarginBounds.Top + e.MarginBounds.Height + 31); } }} 示例工程下载:testPrint
在我参与的项目中,自打微软的 AJAX 提供了“ModalPopupExtender”这个玩意以后,网页上的提示信息或错误信息较多地采用了模式弹出的方式,用户体验更友好,效果也更酷。当然有时侯,需要在前台js中进行一些输入检查之类的操作,然后用对应的错误信息去设置弹出域中的错误文本,然后再让域弹出。如果全是中文的网站,的确没有什么问题。js直接设置一下弹出域中控件的文本即可。但是考虑到国家化的时候,问题出现了:js中直接写入 msg.innerText = <%$ Resources:Resource,msg1%> 这样的语句会报错。考虑再三,虽然不能直接使用资源文件,那么就间接的使用。1 页面上放几个Label,其文本设置为资源文件中的错误信息,需要几条信息就放几个Label。然后把它们装在一个div里隐藏起来2 js做msg信息设置时,只需要把msg.innerText 设置为对应错误信息Label的文本即可效果图:(中文)(英文)(日文)示例程序下载
介绍大家三个在项目中用到的DataTable的小巧实用的方法(排序、检索、合并): 一、排序1 获取DataTable的默认视图2 对视图设置排序表达式3 用排序后的视图导出的新DataTable替换就DataTable(Asc升序可省略,多列排序用","隔开) DataView dv = dt.DefaultView; dv.Sort = "id Asc,name Desc";dt = dv.ToTable(); 二、检索1 设置查询字符串2 使用Select方法获取到所有满足条件的数据行对象数组(多项查询条件间,用and隔开.模糊查询使用 like %) DataRow[] matches = dt.Select("(id<'003') and (name='名字11') and (number like '%2007%')");string strName = matches[0]["name"].ToString(); 三、合并假定有2个DataTable:Dt1 , Dt2。表结构一样将Dt2接在Dt1后可采用此方法 dt1.Merge(dt2);
缓存迷惑:项目中用到了股票代码的输入框,想使用经典ajax效果——自动完成。 可是与头头讨论时,头头觉得一输入字符就要服务器相应,而且预计的使用人数有点大的情况下,太耗服务器资源了。说服不了头头,只有采用变通的方式,把代码表放到js里,使用纯js实现自动完成功能。头头勉强接受。 网上搜索了一圈,发现不少比较好的使用例子,例如:http://www.javascript-examples.com/autocomplete-demo/ 有个疑惑的地方,用户打开页面时,代码表js下载到了本地缓存,如果第二天代码表js内容变了的话,页面打开时,IE会读取缓存里的那个js文件,还是下载新的这个呢?但是如果禁止了客户端缓存的话,一天内多次打开此页面会不会每次重新下载,给用户的感觉又很慢呢?传言:听到一个传言,说ie打开网页时会自动检查那个js文件的发布时间,如果与缓存里不一致,就会下载新的。是否有这个说法啊?解惑实验:经过自己的测试,好像那个传言是真的。做了一下测试,用iis建了一个普通网站,让页面内嵌入使用了一个js。同时打开ie缓存路径进行文件监视 测试1:ie首次打开网页时,js被down到缓存文件夹。上次修改时间、上次访问时间、上次检查时间,这三个属性的值是一致的。 测试2:隔了一分钟,更改了js文件,ie再此打开这个网页,检查到上次修改时间、上次访问时间、上次检查时间,这三个属性的值又是一致的。 测试3:再隔了一分钟,没有更改js文件,ie再此打开这个网页,检查到上次访问时间、上次检查时间,这两个属性的值是一致的,为打开时的时间,但是上次修改时间显示为1分钟前。 实验结果大致认为:ie打开网页时,会检查js文件是否更新,更新的情况下下载新的文件到缓存,如果文件保持不变的话,不重新下载。
看论坛里很多人都在问如果获取GridView当行的问题,当然解决这个问题有好几个方法:1 加RowCommand事件中,判断请求的发出按钮控件名,根据传递的参数来获取当前行中我们需要的参数。2 GridView设置datakeynames方式。……以上方法实现不再累赘。今天给大家介绍一种最方便,也最满足日常思维的好办法:采用控件事件的sender的Parent来获取cell对象,再取cell的上级对象,也就是row对象了。简单吧!示例如下:在第三列中放了一个模板列,放入了一个CheckBox,想法是在选中时,设置第四列Lable状态标识为“T”,取消选中时,第四列Lable状态标识清空CheckBox直接在模板列中双击,加入以下代码即可。 protected void CheckBox1_CheckedChanged(object sender, EventArgs e) { CheckBox chk = (CheckBox) sender; DataControlFieldCell dcf = (DataControlFieldCell)chk.Parent; GridViewRow gvr = (GridViewRow)dcf.Parent; if (chk.Checked) { Label lab = (Label)gvr.Cells[3].FindControl("Label1"); lab.Text = "T"; } else { Label lab = (Label)gvr.Cells[3].FindControl("Label1"); lab.Text = ""; } }
纯属小技巧,高手见笑了。一提到如何在前台JS调用后台C#方法,AJAX成为了必然的想法。只是实现的细节采用AJAX 1.0或者AjaxPro的区别。其实如果不用AJAX,我们也能够很方便地利用JS调用后台方法。步骤如下:1 前台放一个按钮。设置为隐藏。注意:不能直接设置Visible=false的方式,这样的话在ASP.Net 2.0编译后的代码里是找不到这个按钮的。需要设置风格:style="display:none;"2 双击按钮,写入C#方法,或者写一个调用后台其他方法的代码段3 前台JS调用的时候,照如下写,这样可以模拟按钮的点击事件,触发后台方法:document.getElementById("Button2").click();示例ASP.Net页: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title> <script> function go() { document.getElementById("Button2").click(); } </script></head><body> <form id="form1" runat="server"> <div> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="go();return false;" /> <asp:Button ID="Button2" runat="server" Text="Button" OnClick="Button2_Click" Style="display: none;" /> </div> </form></body></html> 后台C#: using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using System.Text;public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void Button2_Click(object sender, EventArgs e) { this.SayHello(); } private void SayHello() { this.TextBox1.Text = "你好,何奎!"; }}
AjaxControlToolkit的日历控件(CalendarExtender)增加了全球化及本地化支持。 只要在<asp:ScriptManager/>中增加EnableScriptGlobalization="true"EnableScriptLocalization="true"两个属性即可
做前台功能设计的时候,遇到以下需求:文本框显示数据库中原来的文本,鼠标点击文本框即变为编辑状态,编辑结束时执行内容存储的后台事件。显示文本时的样式和与编辑状态时的样式风格也要求有不同。实验中遇到以下问题:初次页面展现时,如果文本框输入不正确,触发了验证控件。改变文本框的输入正确后,焦点离开事件顺利执行。当再次将文本框的值输入异常时,验证控件没有显示异常,后台事件依然进行了。显然与逻辑不符合了,用验证控件的目的就是如果前台页面验证不满足的情况下,肯定不允许执行后台事件的。辛苦一番之后,问题解决:验证控件需设置以下2个属性,让其不做客户端脚本处理,直接调后台事件,但又要显示错误信息EnableClientScript="False" Display="Dynamic"同时在后台TextChanged事件中也应检查页面验证的情况 protected void TextBox1_TextChanged(object sender, EventArgs e) { if (Page.IsValid) { [YourCode] } } 为了让使用效果更加友好,把这些控件又放在了UpdatePanel中。不闪的才是最好的。 测试项目ASP.NET代码:(TextBox的样式变更,放在了皮肤文件中) <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <table id="table1" border="0" cellpadding="0" cellspacing="0" width="500"> <tr> <td style="width:47px; font-size: 9pt;" align="center">标题1</td> <td style="width:124px;" align="left"> <asp:TextBox ID="TextBox1" runat="server" SkinID="txtchange" OnTextChanged="TextBox1_TextChanged" CausesValidation="True" AutoPostBack="True">你好啊!</asp:TextBox> </td> <td style="width:200px;" align="left"><asp:RequiredFieldValidator id="RequiredFieldValidator1" runat="server" Width="155px" ErrorMessage="必须输入" Display="Dynamic" EnableClientScript="False" ControlToValidate="TextBox1" Font-Size="Small"></asp:RequiredFieldValidator></tr> <tr> <td style="width:47px; font-size: 9pt;" align="center">标题2</td> <td style="width:124px;" align="left"> <asp:TextBox ID="TextBox2" runat="server" OnTextChanged="TextBox1_TextChanged" SkinID="txtchange" CausesValidation="True" AutoPostBack="True">heekui</asp:TextBox></td> <td style="width:200px;" align="left"> <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ControlToValidate="TextBox2" EnableClientScript="False" Display="Dynamic" ErrorMessage="必须输入" Width="155px" Font-Size="Small"></asp:RequiredFieldValidator></td> </tr> <tr> <td style="width:100%;" colspan="3" align="left"><asp:Label ID="Label1" runat="server" Width="166px" Font-Size="Small" ForeColor="#C04000"></asp:Label> </td> </tr> <tr> <td align="left" colspan="3" style="width: 100%; font-size: 9pt;"> 点击黄色区域,可进行编辑</td> </tr> </table> </ContentTemplate> </asp:UpdatePanel> </div> </form></body></html> 文本框皮肤文件: <asp:TextBox SkinId="txtchange" onblur="this.style.backgroundColor='#FFFACD';this.style.border='solid 0px';" onfocus="this.style.backgroundColor='#FFFFFF';this.style.border='solid 1px';" runat="server" BackColor="#FFFACD" BorderStyle="Solid" BorderWidth="0px" /> 后台代码: using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;public partial class _Default : System.Web.UI.Page { protected void Page_PreInit(object sender, EventArgs e) { this.Theme = "default"; } protected void Page_Load(object sender, EventArgs e) { } protected void TextBox1_TextChanged(object sender, EventArgs e) { if (Page.IsValid) { string strOut = this.TextBox1.Text + " " + this.TextBox2.Text; this.Label1.Text = strOut; } }} 示例工程下载:/Files/heekui/TxtChange.rar
目前参加项目是从去年开始的,去年用的ATLAS做了一些东西,今天上面要求升级为AJAX 1.0的版本。先从微软网站下载了ASP.NET AJAX 1.0(版本号:1.0.61025.0) 以及 3月2日发布的 AjaxControlToolkit (版本号:1.0.10301.0)接下来就是安装。先从控制面板卸载以前安装的ATLAS,再执行ASPAJAXExtSetup.msi进行安装,安装过程一切顺利。工具栏中选择项目的方式先把AjaxControlToolkit那一套东东更新了,准备用确认按钮测试一下。新建了一个ASP.NET AJAX-Enabled Web Site项目,页面已经自动添加了一个ScriptManager,拖入了一个UpdatePanel,放入一个按钮,再拖了一个ConfirmButtonExtender放在按钮旁边,关联上按钮,写入确认的文本,运行网站。程序报错:The control with ID 'UpdatePanel1' requires a ScriptManager on the page. The ScriptManager must appear before any controls that need it.我怀疑自己的眼睛,ScriptManager 不是已经在页面上了吗?难道'UpdatePanel1'对他视而不见。出问题的代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><%@ Register Assembly="Microsoft.Web.Atlas" Namespace="Microsoft.Web.UI" TagPrefix="cc1" %><%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc2" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> <form id="form1" runat="server"> &nbsp; &nbsp;&nbsp; <cc1:ScriptManager ID="ScriptManager1" runat="server"> </cc1:ScriptManager> &nbsp; &nbsp;&nbsp; <cc1:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /> <asp:Label ID="Label1" runat="server" Text="Label" Width="346px"></asp:Label> <cc2:ConfirmButtonExtender ID="ConfirmButtonExtender1" TargetControlID="Button1" ConfirmText="hekui,确认删除?" runat="server"> </cc2:ConfirmButtonExtender> </ContentTemplate> </cc1:UpdatePanel> </form></body></html> 又检查了一遍代码,发现页面顶上的声明好像有问题:怎么还会出现ATLAS的字样。再检查项目引用,果然还有一个Microsoft.Web.Atlas.dll在,遂删除,并重新添加最新的ajax扩展的三个dll到项目(文件:AJAXExtensionsToolbox.dll、System.Web.Extensions.dll、System.Web.Extensions.Design.dll 所处路径:C:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025)工具栏上再把Microsoft.Web.Atlas的选项去掉,重新添加AJAXExtensionsToolbox.dll的选项。再次放入ScriptManager、UpdatePanel,再次执行程序,一切正常了。耶~~~改正后的代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc2" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> <form id="form1" runat="server"> &nbsp; &nbsp;&nbsp; <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> &nbsp; &nbsp;&nbsp; <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /> <asp:Label ID="Label1" runat="server" Text="Label" Width="346px"></asp:Label> <cc2:ConfirmButtonExtender ID="ConfirmButtonExtender1" TargetControlID="Button1" ConfirmText="hekui,确认删除?" runat="server"> </cc2:ConfirmButtonExtender> </ContentTemplate> </asp:UpdatePanel> </form></body></html>
项目中在UpdatePanel范围内加入了一个GridView控件。如果此页面初始化有数据时,分页效果一切正常。但是当初始化时没有数据,页面中点击按钮加载数据后,再点分页数字时报异常:“Microsoft JScript 运行时错误: 缺少对象”经多方请教,几经周折后,终于搞定这个问题。病因:加入UpdatePanel后,gridview绑定数据属于局部刷新,有些js便没有注册到页面对象中,所以会出现js错误。解决办法:1 设置GridView的OnPageIndexChanging事件,在C#后台写入获取新页面索引,绑定数据的代码。例如: protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e) { GridView1.PageIndex = e.NewPageIndex; GridView1.DataSource = getDt(); GridView1.DataBind(); } 2 前台UpdatePanel内给Gridview绑定数据的按钮中,设置属性:PostBackUrl="~/Default.aspx" 。后面的网页写入当前网页的名称 <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" PostBackUrl="~/Default.aspx" /> 示例代码前台ASPX: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><%@ Register Assembly="C1.Web.C1WebGrid.2" Namespace="C1.Web.C1WebGrid" TagPrefix="C1WebGrid" %><%@ Register Assembly="Microsoft.Web.Atlas" Namespace="Microsoft.Web.UI" TagPrefix="cc1" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server"> <title>无标题页</title></head><body> <form id="form1" runat="server"> <div> <cc1:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True"> <ErrorTemplate> <div style="padding: 12px; width: 400px; height: 140px; border: #000000 1px solid; background-color: white; text-align: left"> An error has occurred:<br /> <span id="errorMessageLabel" runat="server"></span> <br /> <br /> <input id="okButton" runat="server" type="button" value="OK" /> </ErrorTemplate> </cc1:ScriptManager> &nbsp;</div> <cc1:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" PostBackUrl="~/Default.aspx" /> <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" OnPageIndexChanging="GridView1_PageIndexChanging"> <Columns> <asp:TemplateField> <ItemTemplate> <asp:TextBox ID="TextBox1" runat="server" Text=<%# Eval("id") %>></asp:TextBox> </ItemTemplate> </asp:TemplateField> <asp:TemplateField> <ItemTemplate> <asp:TextBox ID="TextBox2" runat="server" Text=<%# Eval("name") %>></asp:TextBox> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="name" /> </Columns> </asp:GridView> </ContentTemplate> </cc1:UpdatePanel> </div> </form></body></html> 后台CS: using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { //this.GridView1.DataSource = this.getDt(); //this.GridView1.DataBind(); } } protected void Button1_Click(object sender, EventArgs e) { this.GridView1.DataSource = this.getDt(); this.GridView1.DataBind(); } private DataTable getDt() { DataTable dt = new DataTable(); dt.Columns.Add("id"); dt.Columns.Add("name"); DataRow dr = null; for (int i = 0; i < 20; i++) { dr = dt.NewRow(); dr["id"] = i.ToString(); dr["name"] = "名字" + i.ToString(); dt.Rows.Add(dr); } return dt; } protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e) { GridView1.PageIndex = e.NewPageIndex; GridView1.DataSource = getDt(); GridView1.DataBind(); }}
30分钟正则表达式指导 by Jim Hollenhorst 译 寒带鱼 你是否曾经想过正则表达式是什么,怎样能够快速得到对它的一个基本的认识?我的目的就是在30分钟内带你入门并且对正则表达式有一个基本的理解。事实是正则表达式并没有它看起来那么复杂。学习它最好的办法就是开始写正则表达式并且不断实践。在最初的30分钟之后,你就应该知道一些基本的结构并且有能力在你的程序或者web页面中设计和使用正则表达式了。对那些想要深入研究的人,现在已经有很多非常好的可用资源来让你更深入的学习。 到底什么是正则表达式? 我相信你对模式匹配的“计算机通配符”字符应该比较熟悉了。例如,如果你想要在一个Windows文件夹中找到所有Mircosoft Word文件,你要搜索“*.doc”,因为你知道星号会被解释为一个通配符,它匹配所有序列的字符串。正则表达式就是这种功能的一个更加细节的扩展。 在写处理文本的程序或者web页面时,定位匹配复杂模式的字符串是很常见的。正则表达式就是用来描述这类模式的。这样,一个正则表达式就是一个模式的缩减代码。例如,模式“\w+”是表达“匹配任何包含字母数字字符的非空字符串”的精确方法。.NET框架提供了一个功能强大类库,它使得在你的应用程序中包含正则表达式更加容易。使用这个库,你可以轻易地搜索和替换文本,解码复杂的标题,解析语言,或者验证文本。 学习正则表达式的神秘的语法的一个好办法是用例子作为开始学习的对象,然后实践创建自己的正则表达式。 让我们开始吧! 一些简单的例子 搜索Elvis 假设你要花费你所有的空余时间来扫描文档来寻找Elvis仍然活着的证据。你可以使用下面的正则表达式来搜索: 1. elvis -- Find elvis 这是搜索精确字符序列的一个完全合法的正则表达式。在.NET中,你可以轻松的设置选项来忽略字符的各种情况,所以这个表达式将会匹配“Elivs”,“ELVIS”,或者“eLvIs”。不幸的是,它也将匹配单词“pelvis”的后五个字母。我们可以改进这个表达式如下: 2. \belvis\b -- Find elvis as a whole word现在事情变得更加有趣了。“\b”是一个特殊代码,它表示“匹配任何单词的开头或结尾的位置”。这个表达式将只匹配完整的拼写为“elvis”的单词,无论是小写的还是大写的情况。 假设你想要找到所有这样的行,在其中单词“elvis”后面都跟着单词“alive”。句点或者点“.”是一个特殊代码匹配除了换行符之外的任何字符。星号“*”表示重复前面的部分有必要的次数以保证能够有一个匹配。这样,“.*”表示“匹配除了换行符之外的任意数目的字符”。现在建立一个表示“搜索在同一行内后面跟着单词‘alive’的单词‘elvis’”的表达式就是一件简单的事了。 3. \belvis\b.*\balive\b -- Find text with "elvis" followed by "alive"仅仅使用几个特殊字符我们就开始创建功能强大的正则表达式了,而且它们已经开始变得难以被我们人类理解了。 让我们看看另一个例子。 确定电话号码的合法性 假设你的web页面收集顾客的7位电话号码,而且你希望验证输入的电话号码是正确的格式,“xxx-xxxx”,这里每个“x”是一个数字。下面的表达式将搜索整个文本寻找这样的一个字符串: 4. \b\d\d\d-\d\d\d\d -- Find seven-digit phone number每个“\d”表示“匹配任何单个数字”。“-”没有特殊的意义并且按照字面解释,匹配一个连字符。要避免繁琐的重复,我们可以使用一个含有相同含义的速记符: 5. \b\d{3}-\d{4} -- Find seven-digit phone number a better way“\d”后面的“{3}”表示“重复前面的字符三次”。 .NET正则表达式的基础 让我们探索一下.NET中正则表达式的基础 特殊字符 你应该知道几个有特殊意义的字符。你已经见过了“\b”,“.”,“*”,和“\d”。要匹配任何空白字符,像空格,制表符和换行符,使用“\s”。相似地,“\w”匹配任何字母数字字符。 让我们尝试更多的例子: 6. \ba\w*\b -- Find words that start with the letter a这个搜索一个单词的开头(\b),然后是一个字母“a”,接着是任意次数重复的字母数字字符(\w*),最后是一个单词的结尾(\b)。 7. \d+ -- Find repeated strings of digits这里,“+”与“*”是相似的,除了它需要至少一次重复。 8. \b\w{6}\b -- Find six letter words在Expresso中测试这几个表达式,然后实践创建你自己的表达式。下面是一个说明有特殊含义的字符的表格: . 匹配除换行符外的任何字符 \w 匹配任何字母数字字符 \s 匹配任何空白字符 \d 匹配任何数字 \b 匹配一个单词的开始或结尾 ^ 匹配字符串的开始 $ 匹配字字符串的结尾 表1 正则表达式的常用特殊字符 开始阶段 特殊字符“^”和“$”被用来搜索那些必须以一些文本开头和(或)以一些文本结尾的文本。特别是在验证输入时特别有用,在这些验证中,输入的整个文本必须要匹配一个模式。例如,要验证一个7位电话号码,你可能要用: 9. ^\d{3}-\d{4}$ -- Validate a seven-digit phone number这是和第5个例子一样的,但是强迫它符合整个文本字符串,匹配文本的头尾之外没有其他字符。通过在.NET中设置“Multiline”选项,“^”和“$”改变他们的意义为匹配一行文本的起点和结束,而不是整个正文字符串。Expresso的例子使用这个选项。 换码字符 当你想要匹配这些特殊字符中的一个时会产生一个错误,像“^”或者“$”。使用反斜线符号来去掉它们的特殊意义。这样,“\^”,“\.”,和“\\”,分别匹配文本字符“^”,“.”,和“\”。 重复 你已经见过了“{3}”和“*”可以指定一个单独字符的重复次数。稍后,你会看到相同的语法怎样用来重复整个子表达式。此外还有其他几种方法来指定一个重复,如下表所示: * 重复任意次数 + 重复一次或多次 ? 重复一次或多次 {n} 重复n次 {n,m} 重复最少n次,最多m次 {n,} 重复最少n次 表2 常用量词 让我们试试几个例子: 10. \b\w{5,6}\b -- Find all five and six letter words 11. \b\d{3}\s\d{3}-\d{4} -- Find ten digit phone numbers 12. \d{3}-\d{2}-\d{4} -- Social security number 13. ^\w* -- The first word in the line or in the text 在设置和不设置“Multiline”选项的时试试最后一个例子,它改变了“^”的含义。 字符集合 搜索字母数字字符,数字,和空白字符是容易的,但如果你需要搜索一个字符集合中的任意字符时怎么办?这可以通过在方括号中列出想要的字符来轻松的解决。这样,“[aeiou]”就能匹配任意韵母,而“[.?!]”就匹配句子末尾的标点。在这个例子中,注意“.”和“?”在方括号中都失去了他们的特殊意义而被解释为文本含义。我们也可以指定一个范围的字符,所以“[a-z0-9]”表示“匹配任何小写字母或者任何数字”。 让我们试试一个搜索电话号码的更加复杂的表达式: 14. \(?\d{3}[) ]\s?\d{3}[- ]\d{4} A ten digit phone number 这个表达式将会搜索几种格式的电话号码,像“(800)325-3535”或者“650 555 1212”。“\(?”搜索0个或1个左圆括号,“[)]”搜索一个右圆括号或者一个空格。“\s?”搜索0个或一个空白字符。不幸的是,它也会找到像“650)555-1212”这样括号没有去掉的情况。在下面,你会看到怎样用可选项解决这个问题。 否定 有些时候我们需要搜索一个字符,它不是一个很容易定义的字符集合的成员。下面的表格说明了这种字符怎样指定: \W 匹配任何非字母数字字符 \S 匹配任何非空白字符 \D 匹配任何非数字字符 \B 匹配非单词开始或结束的位置 [^x] 匹配任何非x字符 [^aeiou] 匹配任何不在aeiou中的字符 表3 怎样指定你不想要东西 15. \S+ -- All strings that do not contain whitespace characters 后面,我们会看到怎样使用“lookahead”和“lookbehind”来搜索缺少更加复杂的模式的情况。 可选项 要从几个可选项中选择,允许符合任何一个的匹配,使用竖杠“|”来分隔可选项。例如,邮政编码有两种,一个是5位的,另一个是9位的加一个连字符。我们可以使用下面的表达式找到任何一种: 16. \b\d{5}-\d{4}\b|\b\d{5}\b -- Five and nine digit Zip Codes 当使用可选项时,顺序是很重要的因为匹配算法将试图先匹配最左面的选择。如果这个例子中的顺序颠倒过来,表达式将只能找到5位的邮政编码,而不会找到9位的。我们可以使用可选项来改进十位电话号码的表达式,允许包含区码无论是通过空白字符还是连字符划分的: 17. (\(\d{3}\)|\d{3})\s?\d{3}[- ]\d{4} -- Ten digit phone numbers, a better way 分组 圆括号可以用来划分一个子表达式来允许重复或者其他特殊的处理,例如: 18. (\d{1,3}\.){3}\d{1,3} -- A simple IP address finder 表达式的第一部分搜索后面跟着一个“\.”的一个一位到三位的数字。这被放在圆括号中并且通过使用修饰符“{3}”被重复三次,后面跟着与之前一样的表达式而不带后缀部分。 不幸的是,这个例子允许IP地址中被分隔的部分是任意的一位,两位,或三位数字,尽管一个合法的IP地址不能有大于255的数字。要是能够算术比较一个获取的数字N使N<256就好了,但是只用正则表达式是不能够办到的。下一个例子使用模式匹配测试了基于第一位数字的多种可选项来保证限制数字的取值范围。这表明一个表达式会变得很笨重,尽管搜索模式的描述是简单的。 19. ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) -- IP finder 一个“回引”用来搜索前面被一个分组捕获的已匹配文本的再现。例如,“\1”表示“匹配分组1中已捕获到的文本”。下面是一个例子: 20. \b(\w+)\b\s*\1\b -- Find repeated words 它的运行过程是先捕获一个分组1中“(\w+)”表示的至少包含一个字母数字字符的字符串,但仅当它是一个单词的开始或结束字符时才行。然后它搜索任意数量的空白字符“\s*”后跟以被捕获的文本“\1”结尾的单词。 在上面的例子中,想要替换分组“(\w+)”这种写法,我们可以把它写成“(?<Word>\w+)”来给这个分组命名为“Word”。一个对这个分组的回引可以写成“\k<Word>”。试试下面的例子: 21. \b(?<Word>\w+)\b\s*\k<Word>\b -- Capture repeated word in a named group 通过使用圆括号,有很多可用的特殊用途的语法元素。一些最常用的归纳如下面这张表格: 捕获 (exp) 匹配exp并且在一个自动计数的分组中捕获它 (?<name>exp) 匹配exp并且在一个命名的分组中捕获它 (?:exp) 匹配exp并且不捕获它 察看 (?=exp) 匹配任何后缀exp之前的位置 (?<=exp) 匹配任何前缀exp之后的位置 (?!exp) 匹配任何未找到的后缀exp之后的位置 (?<!exp) 匹配任何未找到的前缀exp之前的位置 评论 (?#comment) 评论 表4 常用分组结构 前两个我们已经说过了。第三个“(?:exp)”不会改变匹配行为,它只是不像前两个那样捕获已命名的或者计数的分组。 确定察看(Positive Lookaround) 下面四个是所谓的前向或后向断言。它们从当前的匹配向前或向后寻找需要的东西而不在匹配中包含它们。这些表达式匹配一个类似于“^”或“\b”的位置而不匹配任何文本,理解这个是很重要的。由于这个原因,他们也被称为“零宽度断言”。最好用例子来解释它们: “(?=exp)”是“零宽度确定前向断言”。它匹配一个文本中在给定后缀之前的位置,但不在匹配中包含这个后缀: 22. \b\w+(?=ing\b) -- The beginning of words ending with "ing" “(?<=exp)”是“零宽度确定后向断言”。它匹配在给定前缀后面的位置,但不在匹配中包含这个前缀: 23. (?<=\bre)\w+\b -- The end of words starting with "re" 下面这个例子可以用来重复向三位数为一组的数字中插入逗号的例子: 24. (?<=\d)\d{3}\b -- Three digits at the end of a word, preceded by a digit 下面是一个同时搜索前缀和后缀的例子: 25. (?<=\s)\w+(?=\s) -- Alphanumeric strings bounded by whitespace 否定察看(Negative Lookaround) 之前,我说明了怎样搜索一个不是特定字符或一个字符集合的成员的字符。那么如果我们想要简单的验证一个字符没有出现,但是不想匹配任何东西怎么办?例如,如果我们想要搜索其中“q”不是后跟着“u”的单词怎么办?我们可以尝试: 26. \b\w*q[^u]\w*\b -- Words with "q" followed by NOT "u" 运行例子你就会看到如果“q”是一个单词的最后一个字母就不会匹配,比如“Iraq”。这是因为“[^q]”总是匹配一个字符。如果“q”是单词的最后一个字符,它会匹配后面跟着的空白字符,所以这个例子中表达式结束时匹配两个完整的单词。否定察看可以解决这个问题,因为它匹配一个位置而不消耗任何文本。与确定察看一样,它也可以用来匹配一个任意复杂的子表达式的位置,而不仅仅是一个字符。我们现在可以做得更好: 27. \b\w*q(?!u)\w*\b -- Search for words with "q" not followed by "u" 我们使用“零宽度否定前向断言”,“(?!exp)”,只有当后缀“exp”没有出现时它才成功。下面是另一个例子: 28. \d{3}(?!\d) -- Three digits not followed by another digit 相似地,我们可以使用“(?<!exp)”,“零宽度否定后向断言”,来搜索文本中的一个位置,这里前缀“exp”没有出现: 29. (?<![a-z ])\w{7} -- Strings of 7 alphanumerics not preceded by a letter or space 这里是另一个使用后向的例子: 30. (?<=<(\w+)>).*(?=<\/\1>) -- Text between HTML tags 这个使用后向搜索一个HTML标记,而使用前向搜索对应的结束标记,这样,就能获得中间的文本而不包括两个标记。 评论 标点的另一个用法是使用“(?#comment)”语法包含评论。一个更好的办法是设置“Ignore Pattern Whitespace”选项,它允许空白字符插入表达式然后当使用表达式时忽略它。设置了这个选项之后,任何文本每行末尾在数字符号“#”后面的东西都被忽略。例如,我们可以格式化先前的例子如下: 31. Text between HTML tags, with comments (?<= # Search for a prefix, but exclude it <(\w+)> # Match a tag of alphanumerics within angle brackets) # End the prefix .* # Match any text (?= # Search for a suffix, but exclude it <\/\1> # Match the previously captured tag preceded by "/") # End the suffix 贪婪与懒惰 当一个正则表达式有一个可以接受一个重复次数范围的量词(像“.*”),正常的行为是匹配尽可能多的字符。考虑下面的正则表达式: 32. a.*b -- The longest string starting with a and ending with b 如果这被用来搜索字符串“aabab”,它会匹配整个字符串“aabab”。这被称为“贪婪”匹配。有些时候,我们更喜欢“懒惰”匹配,其中一个匹配使用发现的最小数目的重复。表2中所有的量词可以增加一个问号“?”来转换到“懒惰”量词。这样,“*?”的意思就是“匹配任何数目的匹配,但是使用达到一个成功匹配的最小数目的重复”。现在让我们试试懒惰版本的例子(32): 33. a.*?b -- The shortest string starting with a and ending with b 如果我们把这个应用到相同的字符串“aabab”,它会先匹配“aab”然后匹配“ab”。 *? 重复任意次数,但尽可能少 +? 匹配一次或多次,但尽可能少 ?? 重复零次或多次,但尽可能少 {n,m}? 重复最少n次,但不多于m次,但尽可能少 {n,}? 重复最少n次,但尽可能少 表5 懒惰量词 我们遗漏了什么? 我已经描述了很多元素,使用它们来开始创建正则表达式;但是我还遗漏了一些东西,它们在下面的表中归纳出来。这些中的很多都在项目文件中使用额外的例子说明了。例子编号在这个表的左列中列出。 \a 报警字符 \b 通常是单词边界,但是在一个字符集合中它表示退格键 \t 制表符 34 \r 回车 \v 垂直制表符 \f 分页符 35 \n 换行符 \e ESC 36 \nnn ASCII码八进制数为nnn的字符 37 \xnn 十六进制数为nn的字符 38 \unnnn Unicode码为nnnn的字符 39 \cN Control N字符,例如回车(Ctrl-M)就是\cM 40 \A 字符串的开始(像^但是不依赖于多行选项) 41 \Z 字符串的结尾或者\n之前的字符串结尾(忽略多行) \z 字符串结尾(忽略多行) 42 \G 当前搜索的开始阶段 43 \p{name} 命名为name的Unicode类中的任何字符,例如\p{IsGreek} (?>exp) 贪婪子表达式,也被称为非回溯子表达式。它只匹配一次然后就不再参与回溯。 44 (?<x>-<y>exp) or (?-<y>exp) Balancing group. This is complicated but powerful. It allows named capture groups to be manipulated on a push down/pop up stack and can be used, for example, to search for matching parentheses, which is otherwise not possible with regular expressions. See the example in the project file. 45 (?im-nsx:exp) 正则表达式选项为子表达式exp 46 (?im-nsx) Change the regular expression options for the rest of the enclosing group (?(exp)yes|no) The subexpression exp is treated as a zero-width positive lookahead. If it matches at this point, the subexpression yes becomes the next match, otherwise no is used. (?(exp)yes) Same as above but with an empty no expression (?(name)yes|no) This is the same syntax as the preceding case. If name is a valid group name, the yes expression is matched if the named group had a successful match, otherwise the no expression is matched. 47 (?(name)yes) Same as above but with an empty no expression 表6 我们遗漏的东西。左端的列显示了项目文件中说明这个结构的例子的序号 结论 我们已经给出了很多例子来说明.NET正则表达式的关键特性,强调使用工具(如Expresso)来测试,实践,然后是用例子来学习。如果你想要深入的研究,网上也有很多在线资源会帮助你更深入的学习。你可以从访问Ultrapico网站开始。如果你想读一本相关书籍,我建议Jeffrey Friedl写的最新版的《Mastering Regular Expressions》。 Code Project中还有很多不错的文章,其中包含下面的教程: ·An Introduction to Regular Expressions by Uwe Keim ·Microsoft Visual C# .NET Developer's Cookbook: Chapter on Strings and Regular Expressions 注:本文例子可以从Ultrapico网站下载Expresso测试,点这里下载该程序,点这里察看原文。文章引用地址:http://www.cnblogs.com/supersand/archive/2006/01/20/320695.html
模式窗口中点击按钮让父窗口跳转到新的页面,不可用 opener.document.location 方式来设置,只能在父窗口把当前window对象传递到模式窗口,模式窗口使用 dialogArguments 来获得父窗口对象。父窗口(需要把当前页面window对象传递到模式窗口页面) <a href="javascript:Openersub('qy.htm');" >test</a><script>function Openersub(strUrl){ var vTmd=Math.random(); var vReturn=''; var strFeature = 'dialogWidth:530px;dialogHeight:470px;status:0;scroll:1:0;help:0;'; if(strUrl.indexOf('?')>-1) { vReturn=window.showModalDialog(strUrl+'&tmd='+vTmd,window,strFeature); } else { vReturn=window.showModalDialog(strUrl+'?tmd='+vTmd,window,strFeature); } }</script> 弹出的模式窗口 <span>确认跳转到新的页面?<span><p/><input type="button" value="确定" onclick="dialogArguments.location='http://www.baidu.com';window.close()"><input type="button" value="关闭" onclick="window.close()">
VS2005中提供了代码段的便捷功能,敲入一个关键字,当其在下拉列表中显示图标为一个文件的时候,敲两下TAB键,便能快速的获取这个代码片段,剩下所需做的就是移动到对应的位置,填入参数性质的东西替换预留的位置。当然大多数常见的代码段,微软都为我们提前准备了。例如:if,for ……但是,有时候我们也会遇到重复写两部分或以上数量代码的时候,那么就需要定义我们自己的代码段了。在VS2005中步骤如下:1 文件——新建——文件——XML文件2 在第二行,Ctrl+K ,Ctrl+X列表中选择Snippet3 Title、Author、Description填入对应的内容。Shortcut设置代码段的快捷编码,例如:mysnippet14 有几个预留代码位置,便需要重复几次Literal节点,设置显示的预留位置ID名和默认值5 修改Code节点的Language属性为CSharp(VJSharp,VB,XML)6 Code节点的<![CDATA[ 与 ]]> 之间,填入自己的代码段7 保存,并改变此XML文件的扩展名为snippet,并保存在某个文件夹下8 工具——代码段管理器——添加自己的放代码段文件夹 这样再此在VS2005中写代码时,便可以敲入自编的代码段快捷编码,然后按TAB两次,就能获取到自己的代码段了。在项目中的话,好的代码段也能快捷地供他人分享。一个供参考的示例代码段XML设置文件: <?xml version="1.0" encoding="utf-8" ?><CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <Header> <Title>测试</Title> <Author>何奎</Author> <Shortcut>mysnippet1</Shortcut> <Description>说明</Description> <SnippetTypes> <SnippetType>SurroundsWith</SnippetType> <SnippetType>Expansion</SnippetType> </SnippetTypes> </Header> <Snippet> <Declarations> <Literal> <ID>条件1</ID> <Default>条件1</Default> </Literal> <Literal> <ID>条件2</ID> <Default>条件2</Default> </Literal> </Declarations> <Code Language="CSharp"> <![CDATA[ if($条件1$) { $selected$ $end$; } else if($条件2$) { } ]]> </Code> </Snippet></CodeSnippet> 附加解释:$end$:这是一个特殊参数,用于指定用户在代码段字段中填写完内容并按下 Enter 键后光标所在的位置。$selected$:这是一个特殊参数,只对 SurroundsWith 类型的代码段有意义。
很多时候我们需要链接转向(Url Rewriting),例如二级域名转向、文章访问链接等场合。让我们看两个例子:1 你现在看到的当前作者的博客园的域名:http://heekui.cnblogs.com 实际上是 http://www.cnblogs.com/heekui 的一种链接重写(Url Rewriting)。2 codeproject上的文章,我们获取的地址都是以文章主要关键字做的网页名称:http://www.codeproject.com/cs/webservices/wsdlparser.asp 个人觉得实际的文章链接可能是如下格式(纯属猜想)http://www.codeproject.com/news.asp?id=123456 那么如何在Asp.net2.0中如何实现链接重写呢?可以采用UrlRewritingNet.UrlRewriter.dll来轻松实现UrlRewritingNet.UrlRewriter.dll 可从其官方网站下载:http://www.urlrewriting.net我们要做的就是进行Web.Config文件的设置0 设置之前需要添加引用:UrlRewritingNet.UrlRewriter.dll 1 <configSections>间添加: <configSections> <section name="urlrewritingnet" restartOnExternalChanges="true" requirePermission="false" type="UrlRewritingNet.Configuration.UrlRewriteSection, UrlRewritingNet.UrlRewriter"/> </configSections>2 添加httpModules <httpModules> <add name="UrlRewriteModule" type="UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter"/> </httpModules>3 添加链接重写的设置 <urlrewritingnet rewriteOnlyVirtualUrls="true" contextItemsPrefix="QueryString" defaultPage="default.aspx" defaultProvider="RegEx" xmlns="http://www.urlrewriting.net/schemas/config/2006/07"> <rewrites> <add name="Rewrite1" virtualUrl="^http\://(.*)/UrlRewritingTest/test.aspx" rewriteUrlParameter="ExcludeFromClientQueryString" destinationUrl="~/default.aspx" rewrite="Domain" ignoreCase="true"/> <add name="Rewrite2" virtualUrl="^http\://(.*)/UrlRewritingTest/test1.aspx" rewriteUrlParameter="ExcludeFromClientQueryString" destinationUrl="~/info.aspx?year=2007&amp;month=3&amp;day=9" rewrite="Domain" ignoreCase="true"/> </rewrites> </urlrewritingnet>完整的一个Web.Config文件 <?xml version="1.0"?><configuration> <configSections> <section name="urlrewritingnet" restartOnExternalChanges="true" requirePermission="false" type="UrlRewritingNet.Configuration.UrlRewriteSection, UrlRewritingNet.UrlRewriter"/> </configSections> <urlrewritingnet rewriteOnlyVirtualUrls="true" contextItemsPrefix="QueryString" defaultPage="default.aspx" defaultProvider="RegEx" xmlns="http://www.urlrewriting.net/schemas/config/2006/07"> <rewrites> <add name="Rewrite1" virtualUrl="^http\://(.*)/UrlRewritingTest/test.aspx" rewriteUrlParameter="ExcludeFromClientQueryString" destinationUrl="~/default.aspx" rewrite="Domain" ignoreCase="true"/> <add name="Rewrite2" virtualUrl="^http\://(.*)/UrlRewritingTest/test1.aspx" rewriteUrlParameter="ExcludeFromClientQueryString" destinationUrl="~/info.aspx?year=2007&amp;month=3&amp;day=9" rewrite="Domain" ignoreCase="true"/> <add name="Rewrite3" virtualUrl="^http\://(.*)/UrlRewritingTest/test(\d{4})(\d{2})(\d{2}).aspx" rewriteUrlParameter="ExcludeFromClientQueryString" destinationUrl="~/info.aspx?year=$2&amp;month=$3&amp;day=$4" rewrite="Domain" ignoreCase="true"/> <add name="Rewrite4" virtualUrl="^http\://(.*)/UrlRewritingTest/(\d{4})/(\d{2})/(\d{2})/info.aspx" rewriteUrlParameter="ExcludeFromClientQueryString" destinationUrl="~/info.aspx?year=$2&amp;month=$3&amp;day=$4" rewrite="Domain" ignoreCase="true"/> <add name="Rewrite5" virtualUrl="^http\://(.*)/UrlRewritingTest/stock(\d{6}).aspx" rewriteUrlParameter="ExcludeFromClientQueryString" destinationUrl="~/stockinfo.aspx?code=$2" rewrite="Domain" ignoreCase="true"/> </rewrites> </urlrewritingnet> <appSettings/> <system.web> <httpModules> <add name="UrlRewriteModule" type="UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter"/> </httpModules> <compilation debug="true"/> </system.web></configuration> 示例程序我们做了一个按查询字符串的输入显示对应日期的页面info.aspx protected void Page_Load(object sender, EventArgs e) { string strYear = Request.QueryString["year"].ToString(); string strMonth = Request.QueryString["month"].ToString(); string strDay = Request.QueryString["day"].ToString(); Response.Write(string.Format("你输入的日期是{0}年{1}月{2}日",strYear,strMonth,strDay)); } 常规访问方式:http://localhost/UrlRewritingTest/info.aspx?year=2007&month=03&day=08页面重写方式1:http://localhost/UrlRewritingTest/test20070308.aspx页面重写方式2:http://localhost/UrlRewritingTest/2007/03/08/info.aspx大家可以看到实际的访问效果是一致的。示例文件中还有一个股票信息查看的例子:http://localhost/UrlRewritingTest/stock600616.aspx = http://localhost/UrlRewritingTest/stockinfo.aspx?code=600616示例程序下载:/Files/heekui/UrlRewritingTest.rar
GridView中的超级链接,可以设置一个模版列,放入超级链接的控件,设置绑定参数即可。数据绑定方式有两种,如下示例:Eval方式 <%# Eval("id") %>Bind方式 <%# Bind("id","~/info.aspx?id={0}") %>推荐使用第一种方式,可以在一个<%# %>里放入多个绑定,而第二种只能如此绑定一个值<%# Eval("id") + ":" + Eval("name")%>做超级链接的控件,我们也有多种选择:1 asp:LinkButton 示例 <asp:LinkButton ID="LinkButton2" OnClientClick=<%# "window.open('info.aspx?id=" + Eval("id") + "&name=" + Eval("name") + "')" %> runat="server"><%# "LinkButton方式绑定:" + Eval("id") %></asp:LinkButton> 2 asp:HyperLink示例 <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# "~/info.aspx?id=" + Eval("id") + "&name=" + Eval("name") %>' Text='<%# "HyperLink控件:" + Eval("id") %>'></asp:HyperLink> 3 a标签示例 <a href='<%# "info.aspx?id=" + Eval("id") + "&name=" + Eval("name") %>'>a标签:<%# Eval("id") + ":" + Eval("name")%></a><a href='javascript:alert("<%# "~/info.aspx?id=" + Eval("id") + "&name=" + Eval("name") %>")'>链接js事件:<%# Eval("id") %></a> 绑定多个数据项的时候,也能采用下列方式(推荐使用):<%# String.Format("~/info.aspx?id={0}&name={1}",Eval("id"),Eval("name")) %> LinkButton 不好设置,推荐使用HyperLink或者a的方式,简单实用。特别是a标签,使用javascript的方法也比较方便。
WEB开发有些时候我们会遇到弹出文件对话框,选择一个本地文件的需求。在ASP.NET 2.0下,我们可以直接采用FileUpload控件来做到这一点。这是一个组合控件,由一个文本框和一个按钮组成,实质就是html下的input(file)控件。使用方法:前台<asp:FileUpload ID="FileUpload1" runat="server" /> 后台//获取选择文件完整路径 string fileName = this.FileUpload1.PostedFile.FileName;使用起来没有问题,但是我们会遇到这样一个问题:控件样式不好设置,浏览按钮的文本也不能改变。那么如何可以做到变脸呢?我们只能变通一下,一点小技巧:1 放一个input(file)控件,设置风格为隐藏,属性改变事件中指定选中值赋值到输出的文本框控件上2 放一个input(text)控件,设置为只读3 放一个button控件,设置点击事件为input(file)控件的点击事件 <input type="file" id="btnFile" onpropertychange="txtFoo.value=this.value;" style="visibility:hidden"><br> <input type="text" id="txtFoo" readonly style="width: 353px;background-color:#D6FFD6"> <input type="button" onclick="btnFile.click()" value="选择文件" style="background-color:#E3ECE7;border:1 solid black;"> 这样一次改变,便能修改文本框和按钮的样式和文本,实现变脸。效果图:
打开网页后.在文本框中无法输入文字.并且点鼠标右键也不好用. 原因:修复恶意插件后.破坏了IE内文件. 解决办法:从正常的机器上拷贝c:\windows\system32\mshtmled.dll到本机的system32目录下即可。或者从安装盘中提取该文件.加载mshtmled.dll:在开始-运行中输入:regsvr32 mshtmled.dll
回到家了,没有开发环境,这几天只能看网页学习一下。这是csdn上转载的一篇,有些东东还是值得一看的。1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table border oncontextmenu=return(false)><td>no</table> 可用于Table 2. <body onselectstart="return false"> 取消选取、防止复制 3. onpaste="return false" 不准粘贴 4. oncopy="return false;" oncut="return false;" 防止复制 5. <link rel="Shortcut Icon" href="favicon.ico"> IE地址栏前换成自己的图标 6. <link rel="Bookmark" href="favicon.ico"> 可以在收藏夹中显示出你的图标 7. <input style="ime-mode:disabled"> 关闭输入法 8. 永远都会带着框架<script language="JavaScript"><!--if (window == top)top.location.href = "frames.htm"; //frames.htm为框架网页// --></script> 9. 防止被人frame<SCRIPT LANGUAGE=JAVASCRIPT><!-- if (top.location != self.location)top.location=self.location;// --></SCRIPT> 10. 网页将不能被另存为<noscript><iframe src="/blog/*.html>";</iframe></noscript> 11. <input type=button value=查看网页源代码 onclick="window.location = "view-source:"+ "http://www.williamlong.info""> 12.删除时确认<a href="javascript:if(confirm("确实要删除吗?"))location="boos.asp?&areyou=删除&page=1"">删除</a> 13. 取得控件的绝对位置//Javascript<script language="Javascript">function getIE(e){var t=e.offsetTop;var l=e.offsetLeft;while(e=e.offsetParent)alert("top="+t+"/nleft="+l);}</script> //VBScript<script language="VBScript"><!--function getIE()dim t,l,a,bset a=document.all.img1t=document.all.img1.offsetTopl=document.all.img1.offsetLeftwhile a.tagName<>"BODY"set a = a.offsetParentt=t+a.offsetTopl=l+a.offsetLeftwendmsgbox "top="&t&chr(13)&"left="&l,64,"得到控件的位置"end function--></script> 14. 光标是停在文本框文字的最后<script language="javascript">function cc(){var e = event.srcElement;var r =e.createTextRange();r.moveStart("character",e.value.length);r.collapse(true);r.select();}</script><input type=text name=text1 value="123" onfocus="cc()"> 15. 判断上一页的来源javascript:document.referrer16. 最小化、最大化、关闭窗口<object id=hh1 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11"> <param name="Command" value="Minimize"></object><object id=hh2 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11"> <param name="Command" value="Maximize"></object><OBJECT id=hh3 classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11"><PARAM NAME="Command" VALUE="Close"></OBJECT><input type=button value=最小化 onclick=hh1.Click()><input type=button value=最大化 onclick=hh2.Click()><input type=button value=关闭 onclick=hh3.Click()>本例适用于IE 17.屏蔽功能键Shift,Alt,Ctrl<script>function look(){ if(event.shiftKey) alert("禁止按Shift键!"); //可以换成ALT CTRL} document.onkeydown=look; </script> 18. 网页不会被缓存<META HTTP-EQUIV="pragma" CONTENT="no-cache"><META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"><META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">或者<META HTTP-EQUIV="expires" CONTENT="0"> 19.怎样让表单没有凹凸感?<input type=text style="border:1 solid #000000"> 或<input type=text style="border-left:none; border-right:none; border-top:none; border-bottom: 1 solid #000000"></textarea> 20.<div><span>&<layer>的区别? <div>(division)用来定义大段的页面元素,会产生转行 <span>用来定义同一行内的元素,跟<div>的唯一区别是不产生转行 <layer>是ns的标记,ie不支持,相当于<div> 21.让弹出窗口总是在最上面:<body onblur="this.focus();"> 22.不要滚动条? 让竖条没有: <body style="overflow:scroll;overflow-y:hidden"> </body> 让横条没有: <body style="overflow:scroll;overflow-x:hidden"> </body> 两个都去掉?更简单了 <body scroll="no"> </body> 23.怎样去掉图片链接点击后,图片周围的虚线?<a href="#" onFocus="this.blur()"><img src="/blog/logo.jpg" border=0></a> 24.电子邮件处理提交表单<form name="form1" method="post" action="mailto:****@***.com" enctype="text/plain"> <input type=submit></form> 25.在打开的子窗口刷新父窗口的代码里如何写?window.opener.location.reload() 26.如何设定打开页面的大小<body onload="top.resizeTo(300,200);">打开页面的位置<body onload="top.moveBy(300,200);"> 27.在页面中如何加入不是满铺的背景图片,拉动页面时背景图不动 <STYLE> body {background-image:url(/blog/logo.gif); background-repeat:no-repeat; background-position:center;background-attachment: fixed} </STYLE> 28. 检查一段字符串是否全由数字组成<script language="Javascript"><!--function checkNum(str){return str.match(//D/)==null}alert(checkNum("1232142141"))alert(checkNum("123214214a1"))// --></script> 29. 获得一个窗口的大小document.body.clientWidth; document.body.clientHeight 30. 怎么判断是否是字符if (/[^/x00-/xff]/g.test(s)) alert("含有汉字");else alert("全是字符"); 31.TEXTAREA自适应文字行数的多少<textarea rows=1 name=s1 cols=27 onpropertychange="this.style.posHeight=this.scrollHeight"></textarea> 32. 日期减去天数等于第二个日期<script language=Javascript>function cc(dd,dadd){//可以加上错误处理var a = new Date(dd)a = a.valueOf()a = a - dadd * 24 * 60 * 60 * 1000a = new Date(a)alert(a.getFullYear() + "年" + (a.getMonth() + 1) + "月" + a.getDate() + "日")}cc("12/23/2002",2)</script> 33. 选择了哪一个Radio<HTML><script language="vbscript">function checkme()for each ob in radio1if ob.checked then window.alert ob.valuenextend function</script><BODY><INPUT name="radio1" type="radio" value="style" checked>Style<INPUT name="radio1" type="radio" value="barcode">Barcode<INPUT type="button" value="check" onclick="checkme()"></BODY></HTML> 34.脚本永不出错<SCRIPT LANGUAGE="JavaScript"> <!-- Hide function killErrors() { return true; } window.onerror = killErrors; // --> </SCRIPT> 35.ENTER键可以让光标移到下一个输入框<input onkeydown="if(event.keyCode==13)event.keyCode=9">36. 检测某个网站的链接速度:把如下代码加入<body>区域中:<script language=Javascript>tim=1setInterval("tim++",100)b=1var autourl=new Array()autourl[1]="www.njcatv.net"autourl[2]="javacool.3322.net"autourl[3]="www.sina.com.cn"autourl[4]="www.nuaa.edu.cn"autourl[5]="www.cctv.com"function butt(){document.write("<form name=autof>")for(var i=1;i<autourl.length;i++)document.write("<input type=text name=txt"+i+" size=10 value="/blog/测试中......>" =》<input type=text name=url"+i+" size=40> =》<input type=button value=GO onclick=window.open(this.form.url"+i+".value)><br/>")document.write("<input type=submit value=刷新></form>")}butt()function auto(url)else b++}function run(){for(var i=1;i<autourl.length;i++)document.write("<img src=http://"+autourl+"/"+Math.random()+" width=1 height=1 onerror=auto("http://"+autourl+"")>")}run()</script> 37. 各种样式的光标auto :标准光标default :标准箭头hand :手形光标wait :等待光标text :I形光标vertical-text :水平I形光标no-drop :不可拖动光标not-allowed :无效光标help :?帮助光标all-scroll :三角方向标move :移动标crosshair :十字标e-resizen-resizenw-resizew-resizes-resizese-resizesw-resize 38.页面进入和退出的特效进入页面<meta http-equiv="Page-Enter" content="revealTrans(duration=x, transition=y)">推出页面<meta http-equiv="Page-Exit" content="revealTrans(duration=x, transition=y)"> 这个是页面被载入和调出时的一些特效。duration表示特效的持续时间,以秒为单位。transition表示使用哪种特效,取值为1-23: 0 矩形缩小 1 矩形扩大 2 圆形缩小 3 圆形扩大 4 下到上刷新 5 上到下刷新 6 左到右刷新 7 右到左刷新 8 竖百叶窗 9 横百叶窗 10 错位横百叶窗 11 错位竖百叶窗 12 点扩散 13 左右到中间刷新 14 中间到左右刷新 15 中间到上下 16 上下到中间 17 右下到左上 18 右上到左下 19 左上到右下 20 左下到右上 21 横条 22 竖条 23 以上22种随机选择一种 39.在规定时间内跳转<META http-equiv=V="REFRESH" content="5;URL=http://www.williamlong.info"> 40.网页是否被检索<meta name="ROBOTS" content="属性值"> 其中属性值有以下一些: 属性值为"all": 文件将被检索,且页上链接可被查询; 属性值为"none": 文件不被检索,而且不查询页上的链接; 属性值为"index": 文件将被检索; 属性值为"follow": 查询页上的链接; 属性值为"noindex": 文件不检索,但可被查询链接; 属性值为"nofollow": 文件不被检索,但可查询页上的链接。 最大化窗口?<script language="JavaScript"><!--self.moveTo(0,0)self.resizeTo(screen.availWidth,screen.availHeight)//--></script> 解决问题:由于层与下拉框之间的优先级是:下拉框 > 层,因此在显示的时候,会因为优先级的次序而会出现如上问题。(如果几个元素都是层的话,我们可以通过层的 z-index 属性来设置)解决办法就是:给层中放一个优先级比下拉框更高的元素(iframe),从而解决此问题!具体解决代码如下: <div id="menu" style="position:absolute; visibility:hidden; top:20px; left:20px; width:100px; height:200px; background-color:#6699cc;"><table> <tr><td>item 1</td></tr> <tr><td>item 2</td></tr> <tr><td>item 3</td></tr> <tr><td>item 4</td></tr> <tr><td>item 5</td></tr> </table> <iframe src="/blog/javascript:false" style="position:absolute; visibility:inherit; top:0px; left:0px; width:100px; height:200px; z-index:-1; filter='progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';"></iframe></div> <a href="#" onclick="document.getElementById('menu').style.visibility='visible'">menu</a> <form> <select><option>A form selection list</option></select></form> 输入框也可以做的很漂亮了<div align="center"><input type="hidden" name="hao" value="yes"> 外向数:<input name=answer style="color: rgb(255,0,0); border-left: medium none; border-right: medium none; border-top: medium none; border-bottom: 1px solid rgb(192,192,192)"> 没回答的题数:<input name=unanswer id="unanswer" style="color: rgb(255,0,0); border-left: medium none; border-right: medium none; border-top: medium none; border-bottom: 1px solid rgb(192,192,192)"> <br/> 总得分: <input name=score id="score" style="color: rgb(255,0,0); border-left: medium none; border-right: medium none; border-top: medium none; border-bottom: 1px solid rgb(192,192,192)"> 结 论: <input name=xgjg id="xgjg" style="color: rgb(255,0,0); border-left: medium none; border-right: medium none; border-top: medium none; border-bottom: 1px solid rgb(192,192,192)"> <br/> <br/> <input onClick=processForm(this.form) style="FONT-FAMILY: 宋体; FONT-SIZE: 9pt" type=button value=查看结果 name="button"> <input type="reset" name="Submit" value="重做"> </div>注意:修改<body>为<body onload="max.Click()">即为打开最大 化窗口,而如果改为<body onload="min.Click()">就变为窗口一打开就最小化 <object id="min" type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11"> <param name="Command" value="Minimize"> </object> <object id="max" type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11"> <param name="Command" value="Maximize"> </object></body> 页面自动刷新(说明) 当你做网页时,是不是有的时候想让你的网页自动不停刷新,或者过一段时间自动跳转到另外一个你自己设定的页面?其实实现这个效果非常地简单,而且这个效果甚至不能称之为特效。你只要把如下代码加入你的网页中就可以了。 1,页面自动刷新:把如下代码加入<head>区域中<meta http-equiv="refresh" content="20">,其中20指每隔20秒刷新一次页面. 2,页面自动跳转:把如下代码加入<head>区域中<meta http-equiv="refresh" content="20;url=http://www.williamlong.info">,其中20指隔20秒后跳转到http://www.williamlong.info页面。 页面自动关闭 5000是指时间<body onLoad="setTimeout(window.close, 5000)"> 弹出窗口自动关闭 10秒后弹出窗口自动关闭 注意:在新的tan.htm的body中要加 <onLoad="closeit()">head <script language="JavaScript"> <!-- var gt = unescape('%3e'); var popup = null; var over = "Launch Pop-up Navigator"; popup = window.open('', 'popupnav', 'width=225,height=235,resizable=1,scrollbars=auto'); if (popup != null) { if (popup.opener == null) { popup.opener = self; } popup.location.href = 'tan.htm'; } // --> </script><body>注意:这段代码是在新建文件中的<script language="JavaScript"> function closeit() </script> 这个可不是<iframe>(引用)呀。是直接调用的。以下代码加入<body>区域 <object type="text/x-scriptlet" width="800" height="1000" data="../index.htm"></object>来源:http://community.csdn.net/Expert/topic/5244/5244445.xml?temp=.751507
一直期待ATLAS能够提供AutoComplete的扩展特性,终于不负众望,在最新版的ASP.NET AJAX Control Toolkit 已经包含了这个特性:AutoCompleteExtender。使用起来是很简单的。以下举个股票代码查询的例子,输入部分代码、拼音缩写或者汉字,便能得到全部的提示。1 添加一个TextBox<asp:TextBox runat="server" ID="txtStockKeyName" Width="300" autocomplete="off" />2 添加AutoCompleteExtender,并设置参数<cc1:AutoCompleteExtender runat="server" ID="autoComplete1" TargetControlID="txtStockKeyName" ServicePath="StockCode.asmx" ServiceMethod="GetStockList" MinimumPrefixLength="1" CompletionInterval="1000" EnableCaching="true" CompletionSetCount="12" />参数说明:TargetControlID : 输入查询关键字的文本框ServicePath : 对应后台的Webservice的地址ServiceMethod : 对应后台的Webservice的方法名MinimumPrefixLength :查询关键字长度产生自动完成的最短长度CompletionInterval :查询结果显示间隔时间(毫秒)EnableCaching : 启用CacheCompletionSetCount :显示查询结果的条数 3 根据查询关键字返回查询结果的Webservice方法 using System;using System.Web;using System.Collections;using System.Web.Services;using System.Web.Services.Protocols;using System.Collections.Generic;using System.Collections;/**//// <summary>/// StockCode 的摘要说明/// </summary>[WebService(Namespace = "http://tempuri.org/")][WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)][System.Web.Script.Services.ScriptService]public class StockCode : System.Web.Services.WebService { public StockCode () { //如果使用设计的组件,请取消注释以下行 //InitializeComponent(); } [WebMethod] public string[] GetStockList(string prefixText, int count) { if (count == 0) { count = 10; } Random random = new Random(); List<string> items = new List<string>(count); for (int i = 0; i < stockID.Length; i++) { if ( (stockID[i].IndexOf(prefixText) >= 0) || (stockName[i].IndexOf(prefixText) >= 0) || (stockPY[i].ToUpper().IndexOf(prefixText.ToUpper()) >= 0) ) { items.Add(stockID[i] + ":" + stockName[i]); } } return items.ToArray(); } //股票代码 string[] stockID = { "610001", "610002", "611003", "611004" }; //股票拼音简称 string[] stockPY = { "xg", "ng", "xj", "xc" }; //股票名称 string[] stockName = { "西瓜", "南瓜", "香蕉", "香肠" }; } 效果图:示例代码:/Files/heekui/StockID.rar运行环境:VS2005 + ASP.NET AJAX V 1.0 + ASP.NET AJAX Control Toolkit