Posted by & filed under Programming.

在谈具体实现前 先介绍一下三种事务:
1. 单对象单资源
单事物
2. 多对象单资源
多对象
3. 多对象多资源(分布式事务, 使用两段提交协议)
多对象多资源

在ADO.Net1.0下有两种使用Transaction的方法. 一种是在需要事务的对象中显式的调用事务处理, 还有一种是使用Enterprise Service的声明式的方法.

第一种方法的示例代码如下:

public void TransactionTest()
        {
            string connectionString = "";
            IDbConnection connection = new SqlConnection(connectionString);
            connection.Open();
            IDbCommand command = new SqlCommand();
            command.Connection = connection;
            IDbTransaction transaction;
            transaction = connection.BeginTransaction(); //Enlisting database
            command.Transaction = transaction;
            try
            {
                /**//* Interact with database here, then commit the transaction
                */
                transaction.Commit();
            }
            catch
            {
                transaction.Rollback(); //Abort transaction
            }
            finally
            {
                connection.Close();
            }
        }

这种方法使用起来相当麻烦, 而且只能针对一个对象访问一个资源的事务. 如果事务涉及多个对象,那么由谁来进行事务处理? 如果事务使用了多个资源, 那样又涉及到分布式事务和两段提交协议,此时依靠第一种方法完全由用户自己控制实在过于复杂,因此在提供了第一种基本方法后, ADO.Net 1.0又利用Com+实现了声明式的事务处理,示例代码如下:

using System.EnterpriseServices;
[Transaction]
public class MyComponent : ServicedComponent
{
[AutoComplete]
public void MyMethod()
{
/**//*Interact with other serviced components
and resource managers */
}
}

这种声明式的方法看上去似乎很好,但是也隐含了许多问题.
1. 使用事务的对象需要继承ServicedComponent
2. 即使不涉及多资源的分布式事务而仅仅是涉及到了多个对象的简单事务(开头介绍的第二种事务),我也要使用此方法,影响了效率. 这样的弊端和J2ee中的都在本地的Entity Bean之间进行通讯很像,杀鸡也不得不用牛刀.
3. 不可避免的使用了Com+.
4. 使用Enterprise Services的事务总是线程安全的, 也就是说你无法让多个线程参与到同一个事务中.

ADO.Net2.0 提供的新的事务模型综合了前两者的优点,
1 在简单(不涉及分布式)事务中也可以使用声明式的事务处理方法, 而不必使用Com+容器, ADO.net 2.0中提供了一个轻量级的事务容器.
2 用户根本不需要考虑是简单事务还是分布式事务. 新模型会自动根据事务中涉及的对象资源判断使用何种事务管理器. 简而言之, 对于任何的事务用户只要使用同一种方法进行处理. 示例代码:

using(TransactionScope scope = new TransactionScope())
{
/**//* Perform transactional work here */
//No errors - commit transaction
scope.Complete();
}

另外对嵌套事务和事务的隔离级别也提供了支持, 在此就不作详细介绍. Fantasy Soft对此做了介绍.

using(TransactionScope scope1 = new TransactionScope())
//Default is Required
{
using(TransactionScope scope2 = new 
TransactionScope(TransactionScopeOption.Required))
{}
using(TransactionScope scope3 = new 
TransactionScope(TransactionScopeOption.RequiresNew))
{}
using(TransactionScope scope4 = new 
TransactionScope(TransactionScopeOption.Suppress))
{}
 
}
表格 资源模式
TransactionOptions options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TransactionManager.DefaultTimeout;
using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
 
public enum IsolationLevel
{
ReadUncommitted,
ReadCommitted,
RepeatableRead,
Serializable,
Unspecified,
Chaos, //No isolation whatsoever
Snapshot //Special form of read committed 8
supported by SQL Server 2005
}

本文仅仅是ADO.net 2.0 Transaction的简单介绍, 详细资料查看M$的相关文档.

本文转载自:享受代码,享受人生

Posted by & filed under Programming.

M6上有人问了一个这样的问题:

header(“Location:$url”)
$url从GET传过来时会转到http://127.0.0.1/$url
谁知道原因?

出现这种转向不正确的原因是通过GET方法获取的URL后缀有可能是不正确的,比如带了其他参数等等,而且指定一个准确的相对地址也不容易,所以我们有必要先获取服务器URL,然后再获取后面的字符串地址,再加上我们需要访问的文件名

主要代码如下:

 
<?php
/* Redirect to a different page in the current directory that was requested */
$host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\');
$extra = 'mypage.php';
header("Location: http://$host$uri/$extra");
exit;
?>

PHP手册中也有讲到,具体请点击:PHP手册

最后解释一下为什么要用rtrim()方法,这样做是为了过滤一些被编码的URL,比如查询符号“?”等,具体用法请参考PHP手册里面的解释,我就不罗嗦了。

Posted by & filed under Study & Reading.

刚看了一下我的访问统计,发现很多是通过ghs.google.com这个关键词来的,看来最近ghs.google.com被和谐了之后还是很多人着急的,这里提供一个解决办法,到现在为止还是可以用的,以后会不会被和谐就不知道了。

这个惊天地泣鬼神的方法就是用A记录绑定IP(看官应该知道什么是A记录而且知道怎么绑定的吧,不会请留言 :) )

目前还能用的几个IP

216.239.34.21
216.239.36.21
216.239.38.21

只需选一个就可以了

访问速度请看:用GAE做了个小应用,欢迎大家来玩

更新:2009-3-4

已经全部失效,正在寻找其他解决方案

2009-6-24更新:

72.14.232.215 可以使用

如果IP失效,可以ping 一下

ghs.xiao3.co.cc 会得到最新的IP

如果你为了省麻烦,直接把自己的域名CNAME到ghs.xiao3.co.cc 域名也行

Posted by & filed under Programming.

刚才发现我贴在博客上的那段代码是有误的,现郑重变更如下:

if($db=mysql_connect( $host,$userName,$passwd))

应该变更成:

 
if($db=mysql_connect( $this->host,$this->userName,$this->passwd))

Posted by & filed under Programming.

经过测试,上篇发布的数据库操作代码,在数据库连接上效率出现很大的问题,原因是过多的使用了try……catch语句,消耗了更多的内存资源,经过优化,其代码如下:

<?php
/**
 * 数据库操作类
 */
 
class MySql {
 
	var $user,$pass,$host,$db;
	var $id,$data,$fields,$row,$row_num,$insertid,$version,$query_num=0;
 
	function MySql($host,$user,$pass,$db)
	{
		$this->host = $host;
		$this->pass = $pass;
		$this->user = $user;
		$this->db = $db;
		$this->dbconnect($this->host, $this->user, $this->pass);
		$this->selectdb($this->db);
 
	}
	function dbconnect($host,$user,$pass)
	{
		$this->id = @ mysql_connect($host,$user,$pass) OR
		sysMsg("连接数据库失败,可能是mysql数据库用户名或密码错误");
	}
	function selectdb($db)
	{
		@ mysql_select_db($db,$this->id) OR sysMsg("未找到指定数据库");
	}
 
	function query($sql)
	{
		$query = @ mysql_query($sql,$this->id)
		OR sysMsg("SQL语句执行错误:$sql <br />".$this->geterror());
		$this->query_num();
		return $query;
	}
 
	function fetch_array($query)
	{
		$this->data = @mysql_fetch_array($query);
		return $this->data;
	}
	function query_num()
	{
		$this->query_num++;
	}
	function num_fields($query)
	{
		$this->fields = @mysql_num_fields($query);
		return $this->fields;
	}
	function fetch_row($query)
	{
		$this->row = @mysql_fetch_row($query);
		return $this->row;
	}
 
	function num_rows($query)
	{
		$this->row_num = @mysql_num_rows($query);
		return $this->row_num;
	}
 
	function insert_id()
	{
		$this->insertid = mysql_insert_id();
		return $this->insertid;
	}
 
	function fetch_one_array($sql)
	{
		$query = $this->query($sql);
		$this->data = $this->fetch_array($query);
		return $this->data;
	}
	function geterror()
	{
		return mysql_error();
	}
}
 
?>

Posted by & filed under Programming.

为了使程序拥有更好的扩展性,重用性以及可读性,我对涉及数据库的代码进行了改进,这种改进是并不是浪费时间,因为公司所有的代码都是在团队协作下完成的,你至少让你伙伴读懂你的代码,而不是使他疯掉。
良好的程序结构能大幅降低后期的维护费用,这也是对客户和公司负责,否则您将失去更多的客户,因为你本来可以给他们带来更多的让渡价值,而没有做。
废话不说了,照例看源代码:

<?php
  class OperateDB
  {
  // 	var 	$db;
   	static $host="localhost";
   	static $user="root";
   	static $passwd="";
 
 
   	//连接数据库
    public	function OpenDB()
    {
    	try
    	{
    		if($db=mysql_connect( $host,$user,$passwd))
    		{
    			return $db;
    		}
    		else
    		{
    			throw new exception("Sorry,could not connect to mysql.");
    		}
    	}
    	catch(exception $e)
    	{
    		echo $e->getmessage();
    	}
    }
    //选择数据库
    public function SelectDB($whichdb,$db)
    {
    	try
    	{
 
    		if(!mysql_select_db($whichdb,$db))
    		{
    			throw new exception("Sorry,database could not be opened.");
    		}
 
    	}
    	catch(exception $e)
    	{
    		echo $e->getmessage();
    	}
 
    }
    public function CloseDB($db)
    {
    	mysql_close($db);
    }
 
    public function Query($queryString)
    {
    	if($mysquery=mysql_query("$queryString"))
    	{
    		return $mysquery;
    	}
    	else
    	{
    		echo mysql_error();
    	}
    }
 
 
 
  }
?>

Posted by & filed under Programming.

趁着今天还有点时间,学习一下PHP,说来惭愧,一年前我已经能读懂PHP程序了,但是到现在写过的代码也没超过100行,都是光说不练的,理论知识一大堆,时间的没有。

说来好笑,在数据库查询语句中,我照搬了Java中的样式,结果总是出现“unknown collum”,原来,PHP中就算传入的是参数信息,查询语句中依然要加上单引号。

下面是源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
<html>
<title>
记事本程序
</title>
<body>
<form method="POST" action="#">
标题:<input type="text" name="title" >
<br/>
内容:<br />
			<textarea rows="10" cols="30"  name="content"></textarea>
		<br />
		<input type="submit" value="提交" name="submit" >
	<input type="reset"  value="取消" name="cancel">
 
</form>
 
 
</body>
</html>
<?php
 
	$ti=$_POST["title"];
	$co=$_POST["content"];
	$th=date("Y-m-d");
	//下面定义数据库信息
	$host="localhost";
	$username="root";
	$passwd="";
 
		if($db=mysql_connect($host,$username,$passwd))
		{
			echo "sucessfully connect to database.";
 
			//mysql_close($db);
		}
		else
		{
			throw new exception("sorry ,could not connect to mysql.");
		}
 
	if(!mysql_select_db("test",$db))
	{
		echo "选择表失败";
	}
	//一定要有单引号,否则出错
	$queryString="INSERT INTO notepad (biaoti,neirong,shijian) VALUES ('$ti','$co','$th')";
 
	if(mysql_query($queryString,$db))
	{
		echo"插入成功!";
	}
	else
	{
 
 
		$str=mysql_error();
		echo $str;
	}
	mysql_close($db);
?>

Posted by & filed under Programming, Tools.

花了三十个小时写的winform程序,采用了标准的三层架构实现,并写了到目前为止最完整的文档,包括需求分析报告,测试方案,数据字典,测试报告等等文档,这要归功于我们三位的女同胞,她们完成了报告,我十分的感谢她们

代码结构 登录框 教师界面 管理员界面 学生界面

源代码下载地址:http://code.google.com/p/selectcourse/
源代码SVN地址:svn checkout http://selectcourse.googlecode.com/svn/trunk/ selectcourse-read-only

Posted by & filed under Tools.

最近一些事情忙,再加上本来就懒,很少上网,就算上也只是看下新闻就撤。从今天开始有点空了,准备晚上 回来写一下python,用于Google app engine,写几个有意思的东西玩玩。

世界上伟的事情不知道什么时候又发生了一次,发现自己绑定在Google的域名居然不能用了,第一反应就是Google被盾了,ping了一下,全都是request time out。很早以前想把域名绑在blogspot上,有人告戒我要死掉的,最后出于安全考虑没绑,现在Google推出了Google apps 和Google app engine,个人觉得很有意思,特别是Google app engine和Google apps中的calendar。

我从不在博客上发牢骚,但是今天真的很气愤,我真搞不懂某些心理阴暗的家伙到底怎么了,这些服务碍你事了吗?你们家有亲戚卖虚拟主机的吗?当年百度和Google竞争的时候你们打着爱国的旗号,ok,你们阴谋得逞了,培养了一个太监,最后Google为了生存,也不得不自宫,虽然自宫的程度没有完全令你们满意。

Google blogspot上有XX内容,令你们不爽,可你也不能连其他的一起封了吧!你们的技术是多么的先进啊,每天我上网的内容总是从某个IP上redirect来的,难道这点技术还能难道你们?

不过这也不算荒唐,更好笑的是:把Google earth也封了,说爆露了军事秘密,:)  哈哈,真是个笑话,Google earth 在全球用户超过五千万,就算中国人伟大,不看这些资本主义的东西,外国人不是看了吗?那就不爆露军事机密?不让中国人看就不爆露军事机密了?

Allen说了一句令我佩服的话:谁让你生活在中国呢!对啊,谁让我生活在中国这么伟大而古老的国家呢!

Posted by & filed under Tools.

为什么要帮助firefox创造世界纪录?

1.firefox完全遵从W3C标准,而不是像微软那样以为自己是老大,自己搞一套标准单干

2、firefox从来都不会恶意推广,而IE通过捆绑销售来占领市场

3、firefox对于开源的贡献远远大于微软

4、firefox需要支持

5、使用firefox可以显著改善您的浏览体验

下载体验:Firefox

Download Day - Chinese