存档

2008年11月 的存档

这几天一直在研究Ubuntu,终于把Eclipse,Myeclipse,FLex,NetBeans安装成功了

2008年11月27日 admin 没有评论

这几天一直在研究Ubuntu,终于把Eclipse,Myeclipse,FLex,NetBeans安装成功了,哈哈。

截图如下:

Popularity: 28% [?]

Ubuntu上的Java安装和配置

2008年11月25日 admin 2 条评论

打开终端,执行以下命令,或使用Adept/新立得软件管理器,在其中分别搜索”sun-java6-jre”和”sun-java6-jdk”并标记安装。

sudo apt-get install sun-java6-jre

如果空间富裕,建议安装一个JDK。

sudo apt-get install sun-java6-jdk

提示:安装过程中需要你回答是否同意使用协议(终端中红蓝色的提示界面),此时按tab键至OK,再按回车即可正常安装。

设置当前默认的java解释器:

sudo update-alternatives --config java

执行后会出现类似如下的画面:

There are 2 alternatives which provide `java'.

Selection Alternative
-----------------------------------------------
1 /usr/bin/gij-wrapper-4.1
*+ 2 /usr/lib/jvm/java-6-sun/jre/bin/java

Press enter to keep the default[*], or type selection number:

输入 有包含 “sun” 的行的前面的数字。如上面显示,则输入2,然后回车确定。


配置JAVA环境变量:

sudo gedit /etc/environment

在其中添加如下两行:

CLASSPATH=.:/usr/lib/jvm/java-6-sun/lib
JAVA_HOME=/usr/lib/jvm/java-6-sun
sudo gedit /etc/jvm

将文件中的

/usr/lib/jvm/java-6-sun

这一行填入到配置块的顶部

安装浏览器的JAVA Plugin(可选):

sudo apt-get install sun-java6-plugin
详细请阅读:UbuntuWiki

Popularity: 20% [?]

分类: JAVA 标签:

Enterprise Library 4.1和Unity 1.2发布

2008年11月21日 admin 没有评论

微软模式与实践团队今天发布了Enterprise Library 4.1和Unity 1.2版本,这次发布的主要新特性如下:

1. 支持Visual Studio 2008 SP1

2. Unity应用程序块中加入了拦截机制

3. 性能提升

4. 配置工具的可用性提升

5. Bugs修复。

在Unity 1.2中有如下几点改进:

1. 简化了对象的创建,尤其是层次对象的结构和依赖

2. 通过为容器推迟组件的配置增加了灵活性

3. 服务定位能力增强,允许客户存储或者缓存容器

4. 实例和类型拦截

下载

下载Enterprise Library 4.1

下载Unity Application Block

下载Unity Documents

Popularity: 25% [?]

强烈推荐:微软应用程序架构指导包v2.0

2008年11月21日 admin 没有评论

应用程序架构指导包由微软模式与实践团队负责编写,为基于.NET平台的应用程序设计提供了一些指导,现在v2.0 Beta版本已经发布,包括的内容有应用程序架构基础、设计、分层、设计模式等等,设计的应用程序类型有Mobile Application,Office Business Application (OBA),Rich Client Application ,Rich Internet Application (RIA),Web Application等 ,之前园子里的蜡笔小巢也有过介绍。完整的目录如下所示:

Parts

Part I, Fundamentals of Application Architecture
Part II, Design
Part III, Layers
Part IV, Quality Attributes
Part V, Archetypes – Design and Patterns

Chapters

Part I, Fundamentals of Application Architecture

Part II, Design

Part III, Layers

Part IV, Quality Attributes

Part V, Archetypes – Design and Patterns

Appendix

下载地址:http://www.codeplex.com/AppArchGuide

Popularity: 19% [?]

Installsheild之Assistant

2008年11月16日 admin 没有评论

经简绍说installsheild不错,打包方便快捷,于是要来软件,安装的是InstallSheild x英文版。

如下图,这是打开的见面,红线是我画上的,点击这条语句就开始新建工程了。


弹出对话框中默认的
InstallScript Project(如下图) 正是我们所需(以Script的方式来完成更多任务)。填入你要打包的项目名,和要释放的位置(打成的包要放的位置),(什么?你说我打的怎么是TTplay,不好意思,TTplay确实是别人的,要先试验再动真格的,要不就元气大伤了。把安装了的TTplay打成包不是很简单的试验方式么。一来就把你几百兆的软件拿过来打,又慢风险又大。你也不知道刚用的软件会发生些什么事故,保险起见,把安装在你电脑里的整个TTplay的文件夹考到一个地方备用。才2点几兆,尽情试验吧)。点击Ok进入下一步。


于是你就见到了
Project Assistantinstall Designer.如下图所示
我们就叫
Project Assistant为工程助理吧,用工程助理就可以完成一般的打包工作,只要点击最下排图标,从左至右来按向导填写就行,网上应该有简绍的,但我还是要唠叨,好像这儿会更有特色。你也完全可以在install Designer里全部完成,但通常都是结合着用。


Project Assistant共九步形成一个安装流程。

点击第一个Application Files,如下图

以此是公司名称、应用软件名称、版本、公司首页。最后的选项是是否自动提醒更新。

生成的软件安装后会以你的公司名为文件夹,应用软件名称为其子文件夹,接着是你的放进去的文件夹(后面会讲到),很多时候你可能不需要这么多文件夹嵌套,像我打包的文件夹就不要应用软件名称,否则,所设置的环境变量就不好处理了,但这的试验就不用管了,后面具体讲。你要根据你所需的文件结构来决定。


点击
installation Architecture,如下图,只有一个选择项,问你是否要个性化安装,意思就是可以选择部分安装,我们就不管了,我们都是要全装的,哈,而且这儿也很简单。(还是说说吧,点选yes,点击New,添加文件夹,取个名字,Set Default来设计你选定要做默认安装的,下一步骤是选定你要打包的文件,其中All Application下拉框选项就会发现刚才你new的文件,选定谁,当前放进的包就属于它了,好像有点抽象,看看想想就应该明白了)


点击
Application Files看到如下图

我们要全安装所以用All Application Data,下面的Destination Computer中的重点文件夹是Application Target Folder,其意义就是客户所选路径+公司名+软件名这样一个路径。

Program Files 是绝对路径”C:”Program Files“群里有哥们为要放一些文件到这个绝对路径,问了几天人,告他用Indesigner中的Program Files,他没明白,效果和项目助手的一样。

Windows也是绝对路径,”C:”WINDOWS“下属分别为”C:”WINDOWS”Fonts“和”C:”WINDOWS”system32


这儿还没操作呢,开始操作,点选
Application Target Folder,点击Add Folders 选定你打包的文件夹,确定就会在Application Target Folder里显示你的文件结构,这可是个慢动作,文件越多就越慢,实际它只是记录了你的文件结构,并非复制。结果如下图:

如果你看不到,很正常,这是它的一个bug,点一下其他的步骤,再点回来就看到了(点回来有时也要你一些时间,bug呀)


点击下一个步骤
Application Redistributables,如下图:

就是问你用不用ODBCsql Server 2000 等等的,都不管了,我们喜欢用开源的。


点击下一步骤
Application Shortcuts,即应用程序快捷方式,如下图


它自动帮你提起你所给文件夹下的
exe,你的软件要没exe就先生成exe,以后会讲到

你的问题出来了,要是exe不在所给文件夹下怎么办,你就点new,弹出窗口展示的是DefaultFeature里的文件分类(如下图),文件分类和前面讲的一样,Application Target Folder 是客户所选路径+公司名+软件名这样一个路径……回忆起来俺就不废话了。大部分情况点击Application Target Folder到你提供的文件夹里找到你的exe就有了。


点选你的
exe,然后在右边的复选框选择是否创建开始菜单快捷方式和桌面快捷方式(看下图)。点选并删除你不用的exe。你可能觉得这样方式真好,后面你会发现工程助手的方式不如Install Designer 的方式好,工程助手可能会令你反复弄来弄去。


下一步
Aplication Registry,如下图:

你就需要选择一个根目录,然后不断点右键新建选项,最后定变量-数值对就行


如下图,新建一次后,再次新建里就可以新建各种值,或者选择导入
Reg的方式,具体自己研究了。也是Install Designer 的方式更好。这儿什么都不需要注册,把刚加的删了。


下一步
Installation Interview 如下图:

共四个选项,第一个选项是是否要license,是的话你要提供一个txtlicense或者写一段脚本来处理。我们选择否。

第二个选项是是否填入公司名和用户名,不用了,我们这不用那么麻烦客户。

第三选项说是否让客户选择安装目录,默认就行(yes)。

第四选项说是否同意客户只安装部分。也默认就行(yes)。


下一步骤
Installation Localization 安装本地化,如下图:

选上简体中文。All String Data等功能和All Application Data的意义是一样的就是看你要整个处理还是安装某部分才这样处理。我们用默认的就行。


最后一步
Build Installation 就是生成你的软件了。如下图:

三个选项意义就是生成单个执行文件、网络版、光盘版。

点击Build Installations就开始建造了。这个过程也有点慢,毕竟要把所有文件存储到一个dat文件里。


结果如下图:


点击
setup.exe就可以安装了。

当然这样的效果可能不如你想象的好,例如点开可能是英文的,你就急了,不是本地化了吗?你忘了看,同时选中的English上有个红勾,表示它是默认语言,要么你把英语的去掉,要么你上Install Designer处理。

如果你已经安装过这个setup.exe,再次点击时它就会提醒你是要修改、修复还是卸载,如下图:


这就是
InstallSheild用向导打包软件的简单过程。你应该知道有exe的软件怎么打包了,下次讲InstallSheildinstall Designer的方式,它能满足你更多的需求。能解决你在工程助手这令人抓狂的问题。

错漏之处,谢谢指正。

Popularity: 21% [?]

SQL Server死锁

2008年11月16日 admin 没有评论

本文收藏博客园的,哈哈。。。。。

1. 死锁原理

根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

死锁的四个必要条件:
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

对应到SQL Server中,当在两个或多个任务中,如果每个任务锁定了其他任务试图锁定的资源,此时会造成这些任务永久阻塞,从而出现死锁;这些资源可能是:单行(RID,堆中的单行)、索引中的键(KEY,行锁)、页(PAG8KB)、区结构(EXT,连续的8)、堆或B(HOBT) 、表(TAB,包括数据和索引)、文件(File,数据库文件)、应用程序专用资源(APP)、元数据(METADATA)、分配单元(Allocation_Unit)、整个数据库(DB)一个死锁示例如下图所示:


说明:
T1T2表示两个任务;R1R2表示两个资源;由资源指向任务的箭头(R1->T1R2->T2)表示该资源被改任务所持有;由任务指向资源的箭头(T1->S2T2->S1)表示该任务正在请求对应目标资源;
其满足上面死锁的四个必要条件:
(1).互斥:资源S1S2不能被共享,同一时间只能由一个任务使用;
(2).请求与保持条件:T1持有S1的同时,请求S2T2持有S2的同时请求S1
(3).非剥夺条件:T1无法从T2上剥夺S2T2也无法从T1上剥夺S1
(4).循环等待条件:上图中的箭头构成环路,存在循环等待。

2. 死锁排查

(1). 使用SQL Server的系统存储过程sp_whosp_lock,可以查看当前数据库中的锁情况;进而根据objectID(@objID)(SQL Server 2005)/ object_name(@objID)(Sql Server 2000)可以查看哪个资源被锁,用dbcc ld(@blk),可以查看最后一条发生给SQL ServerSql语句;

CREATE Table #Who(spid int,
ecid
int,
status
nvarchar(50),
loginname
nvarchar(50),
hostname
nvarchar(50),
blk
int,
dbname
nvarchar(50),
cmd
nvarchar(50),
request_ID
int);

CREATE Table #Lock(spid int,
dpid
int,
objid
int,
indld
int,
[Type] nvarchar(20),
Resource
nvarchar(50),
Mode
nvarchar(10),
Status
nvarchar(10)
);

INSERT INTO #Who
EXEC sp_who active 看哪个引起的阻塞,blk
INSERT INTO #Lock
EXEC sp_lock 看锁住了那个资源id,objid

DECLARE @DBName nvarchar(20);
SET @DBName=NameOfDataBase

SELECT #Who.* FROM #Who WHERE dbname=@DBName
SELECT #Lock.* FROM #Lock
JOIN #Who
ON #Who.spid=#Lock.spid
AND dbname=@DBName;

最后发送到SQL Server的语句
DECLARE crsr Cursor FOR
SELECT blk FROM #Who WHERE dbname=@DBName AND blk<>0;
DECLARE @blk int;
open crsr;
FETCH NEXT FROM crsr INTO @blk;
WHILE (@@FETCH_STATUS = 0)
BEGIN;
dbcc inputbuffer(@blk);
FETCH NEXT FROM crsr INTO @blk;
END;
close crsr;
DEALLOCATE crsr;

锁定的资源
SELECT #Who.spid,hostname,objid,[type],mode,object_name(objid) as objName FROM #Lock
JOIN #Who
ON #Who.spid=#Lock.spid
AND dbname=@DBName
WHERE objid<>0;

DROP Table #Who;
DROP Table #Lock;


(2).
使用 SQL Server Profiler 分析死锁: Deadlock graph 事件类添加到跟踪。此事件类使用死锁涉及到的进程和对象的 XML 数据填充跟踪中的 TextData 数据列。SQL Server 事件探查器 可以将 XML 文档提取到死锁 XML (.xdl) 文件中,以后可在 SQL Server Management Studio 中查看该文件。

3. 避免死锁

上面1中列出了死锁的四个必要条件,我们只要想办法破其中的任意一个或多个条件,就可以避免死锁发生,一般有以下几种方法(FROM Sql Server 2005联机丛书)
(1).按同一顺序访问对象。(注:避免出现循环)
(2).避免事务中的用户交互。(注:减少持有资源的时间,较少锁竞争)
(3).保持事务简短并处于一个批处理中。(注:同(2),减少持有资源的时间)
(4).使用较低的隔离级别。(注:使用较低的隔离级别(例如已提交读)比使用较高的隔离级别(例如可序列化)持有共享锁的时间更短,减少锁竞争)
(5).使用基于行版本控制的隔离级别2005中支持快照事务隔离和指定READ_COMMITTED隔离级别的事务使用行版本控制,可以将读与写操作之间发生的死锁几率降至最低:
SET ALLOW_SNAPSHOT_ISOLATION ON –事务可以指定 SNAPSHOT 事务隔离级别;
SET READ_COMMITTED_SNAPSHOT ON 指定 READ_COMMITTED 隔离级别的事务将使用行版本控制而不是锁定。默认情况下(没有开启此选项,没有加with nolock提示)SELECT语句会对请求的资源加S(共享锁);而开启了此选项后,SELECT不会对请求的资源加S锁。
注意:设置 READ_COMMITTED_SNAPSHOT 选项时,数据库中只允许存在执行 ALTER DATABASE 命令的连接。在 ALTER DATABASE 完成之前,数据库中决不能有其他打开的连接。数据库不必一定要处于单用户模式中。
(6).使用绑定连接(注:绑定会话有利于在同一台服务器上的多个会话之间协调操作。绑定会话允许一个或多个会话共享相同的事务和锁(但每个回话保留其自己的事务隔离级别),并可以使用同一数据,而不会有锁冲突。可以从同一个应用程序内的多个会话中创建绑定会话,也可以从包含不同会话的多个应用程序中创建绑定会话。在一个会话中开启事务(begin tran)后,调用exec sp_getbindtoken @Token out;来取得Token,然后传入另一个会话并执行EXEC sp_bindsession @Token来进行绑定(最后的示例中演示了绑定连接)

4. 死锁处理方法:

(1). 根据2中提供的sql,查看那个spid处于wait状态,然后用kill spid来干掉(即破坏死锁的第四个必要条件:循环等待);当然这只是一种临时解决方案,我们总不能在遇到死锁就在用户的生产环境上排查死锁、Kill sp,我们应该考虑如何去避免死锁。

(2). 使用SET LOCK_TIMEOUT timeout_period(单位为毫秒)设定锁请求超时。默认情况下,数据库没有超时期限(timeout_period值为-1,可以用SELECT @@LOCK_TIMEOUT来查看该值,即无限期等待)。当请求锁超过timeout_period时,将返回错误。timeout_period值为0时表示根本不等待,一遇到锁就返回消息。设置锁请求超时,破环了死锁的第二个必要条件(请求与保持条件)

服务器: 消息 1222,级别 16,状态 50,行 1
已超过了锁请求超时时段。

(3). SQL Server内部有一个锁监视器线程执行死锁检查,锁监视器对特定线程启动死锁搜索时,会标识线程正在等待的资源;然后查找特定资源的所有者,并递归地继续执行对那些线程的死锁搜索,直到找到一个构成死锁条件的循环。检测到死锁后,数据库引擎 选择运行回滚开销最小的事务的会话作为死锁牺牲品,返回1205 错误,回滚死锁牺牲品的事务并释放该事务持有的所有锁,使其他线程的事务可以请求资源并继续运行。

5. 两个死锁示例及解决方法

5.1 SQL死锁

(1). 测试用的基础数据:

CREATE TABLE Lock1(C1 int default(0));
CREATE TABLE Lock2(C1 int default(0));
INSERT INTO Lock1 VALUES(1);
INSERT INTO Lock2 VALUES(1);

(2). 开两个查询窗口,分别执行下面两段sql

Query 1
Begin Tran
Update Lock1 Set C1=C1+1;
WaitFor Delay 00:01:00;
SELECT * FROM Lock2
Rollback Tran;
Query 2
Begin Tran
Update Lock2 Set C1=C1+1;
WaitFor Delay 00:01:00;
SELECT * FROM Lock1
Rollback Tran;

上面的SQL中有一句WaitFor Delay ‘00:01:00′,用于等待1分钟,以方便查看锁的情况。

(3). 查看锁情况

在执行上面的WaitFor语句期间,执行第二节中提供的语句来查看锁信息:

Query1中,持有Lock1中第一行(表中只有一行数据)的行排他锁(RID:X),并持有该行所在页的意向更新锁(PAG:IX)、该表的意向更新锁(TAB:IX)Query2中,持有Lock2中第一行(表中只有一行数据)的行排他锁(RID:X),并持有该行所在页的意向更新锁(PAG:IX)、该表的意向更新锁(TAB:IX)

执行完WaitforQuery1查询Lock2,请求在资源上加S锁,但该行已经被Query2加上了X锁;Query2查询Lock1,请求在资源上加S锁,但该行已经被Query1加上了X锁;于是两个查询持有资源并互不相让,构成死锁。

(4). 解决办法

a). SQL Server自动选择一条SQL作死锁牺牲品:运行完上面的两个查询后,我们会发现有一条SQL能正常执行完毕,而另一个SQL则报如下错误:

服务器: 消息 1205,级别 13,状态 50,行 1
事务(进程 ID  xx)与另一个进程已被死锁在  lock 资源上,且该事务已被选作死锁牺牲品。请重新运行该事务。

这就是上面第四节中介绍的锁监视器干活了。

b). 按同一顺序访问对象:颠倒任意一条SQL中的UpdateSELECT语句的顺序。例如修改第二条SQL成如下:

Query2
Begin Tran
SELECT * FROM Lock1在Lock1上申请S锁
WaitFor Delay 00:01:00;
Update Lock2 Set C1=C1+1;Lock2:RID:X
Rollback Tran;

当然这样修改也是有代价的,这会导致第一条SQL执行完毕之前,第二条SQL一直处于阻塞状态。单独执行Query1Query2需要约1分钟,但如果开始执行Query1时,马上同时执行Query2,则Query2需要2分钟才能执行完;这种按顺序请求资源从一定程度上降低了并发性。

c). SELECT语句加With(NoLock)提示:默认情况下SELECT语句会对查询到的资源加S(共享锁)S锁与X(排他锁)不兼容;但加上With(NoLock)后,SELECT不对查询到的资源加锁(或者加Sch-S锁,Sch-S锁可以与任何锁兼容);从而可以是这两条SQL可以并发地访问同一资源。当然,此方法适合解决读与写并发死锁的情况,但加With(NoLock)可能会导致脏读。

SELECT * FROM Lock2 WITH(NOLock)
SELECT * FROM Lock1 WITH(NOLock)

d). 使用较低的隔离级别。SQL Server 2000支持四种事务处理隔离级别(TIL),分别为:READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLESQL Server 2005中增加了SNAPSHOT TIL默认情况下,SQL Server使用READ COMMITTED TIL,我们可以在上面的两条SQL前都加上一句SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED,来降低TIL以避免死锁;事实上,运行在READ UNCOMMITTED TIL的事务,其中的SELECT语句不对结果资源加锁或加Sch-S锁,而不会加S锁;但还有一点需要注意的是:READ UNCOMMITTED TIL允许脏读,虽然加上了降低TIL的语句后,上面两条SQL在执行过程中不会报错,但执行结果是一个返回1,一个返回2,即读到了脏数据,也许这并不是我们所期望的。

e). SQL前加SET LOCK_TIMEOUT timeout_period,当请求锁超过设定的timeout_period时间后,就会终止当前SQL的执行,牺牲自己,成全别人。

f). 使用基于行版本控制的隔离级别(SQL Server 2005支持):开启下面的选项后,SELECT不会对请求的资源加S锁,不加锁或者加Sch-S锁,从而将读与写操作之间发生的死锁几率降至最低;而且不会发生脏读。

SET ALLOW_SNAPSHOT_ISOLATION ON
SET READ_COMMITTED_SNAPSHOT ON

g). 使用绑定连接(使用方法见下一个示例。)

5.2 程序死锁(SQL阻塞)

看一个例子:一个典型的数据库操作事务死锁分析,按照我自己的理解,我觉得这应该算是C#程序中出现死锁,而不是数据库中的死锁;下面的代码模拟了该文中对数据库的操作过程:

//略去的无关的code
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
SqlTransaction tran
= conn.BeginTransaction();
string sql1 = Update Lock1 SET C1=C1+1;
string sql2 = SELECT * FROM Lock1;
ExecuteNonQuery(tran, sql1);
//使用事务:事务中Lock了Table
ExecuteNonQuery(null, sql2); //新开一个connection来读取Table

public static void ExecuteNonQuery(SqlTransaction tran, string sql)
{
SqlCommand cmd
= new SqlCommand(sql);
if (tran != null)
{
cmd.Connection
= tran.Connection;
cmd.Transaction
= tran;
cmd.ExecuteNonQuery();
}

else
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
cmd.Connection
= conn;
cmd.ExecuteNonQuery();
}

}

}

执行到ExecuteNonQuery(null, sql2)时抛出SQL执行超时的异常,下图从数据库的角度来看该问题:

代码从上往下执行,会话1持有了表Lock1X锁,且事务没有结束,回话1就一直持有X锁不释放;而会话2执行select操作,请求在表Lock1上加S锁,但S锁与X锁是不兼容的,所以回话2的被阻塞等待,不在等待中,就在等待中获得资源,就在等待中超时。。。从中我们可以看到,里面并没有出现死锁,而只是SELECT操作被阻塞了。也正因为不是数据库死锁,所以SQL Server的锁监视器无法检测到死锁。

我们再从C#程序的角度来看该问题:

C#程序持有了表Lock1上的X锁,同时开了另一个SqlConnection还想在该表上请求一把S锁,图中已经构成了环路;太贪心了,结果自己把自己给锁死了。。。

虽然这不是一个数据库死锁,但却是因为数据库资源而导致的死锁,上例中提到的解决死锁的方法在这里也基本适用,主要是避免读操作被阻塞,解决方法如下:

a). SELECT放在Update语句前:SELECT不在事务中,且执行完毕会释放S锁;
b). SELECT也放加入到事务中:ExecuteNonQuery(tran, sql2);
c). SELECTWith(NOLock)提示:可能产生脏读;
d). 降低事务隔离级别:SELECT语句前加SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;同上,可能产生脏读;
e). 使用基于行版本控制的隔离级别(同上例)。
g). 使用绑定连接:取得事务所在会话的token,然后传入新开的connection中;执行EXEC sp_bindsession @Token后绑定了连接,最后执行exec sp_bindsession null;来取消绑定;最后需要注意的四点是:
(1). 使用了绑定连接的多个connection共享同一个事务和相同的锁,但各自保留自己的事务隔离级别;
(2). 如果在sql3字符串的“exec sp_bindsession null”换成“commit tran”或者“rollback tran”,则会提交整个事务,最后一行C#代码tran.Commit()就可以不用执行了(执行会报错,因为事务已经结束了-,-)
(3). 开启事务(begin tran)后,才可以调用exec sp_getbindtoken @Token out来取得Token;如果不想再新开的connection中结束掉原有的事务,则在这个connection close之前,必须执行“exec sp_bindsession null”来取消绑定连接,或者在新开的connectoin close之前先结束掉事务(commit/tran)
(4). (Sql server 2005 联机丛书)后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。 请改用多个活动结果集 (MARS) 或分布式事务。

tran = connection.BeginTransaction();
string sql1 = Update Lock1 SET C1=C1+1;
ExecuteNonQuery(tran, sql1);
//使用事务:事务中Lock了测试表Lock1
string sql2 = @”DECLARE @Token varchar(255);
exec sp_getbindtoken @Token out;
SELECT @Token;
;
string token = ExecuteScalar(tran, sql2).ToString();
string sql3 = EXEC sp_bindsession @Token;Update Lock1 SET C1=C1+1;exec sp_bindsession null;;
SqlParameter parameter
= new SqlParameter(@Token, SqlDbType.VarChar);
parameter.Value
= token;
ExecuteNonQuery(
null, sql3, parameter); //新开一个connection来操作测试表Lock1
tran.Commit();

附:锁兼容性(FROM SQL Server 2005 联机丛书)

锁兼容性控制多个事务能否同时获取同一资源上的锁。如果资源已被另一事务锁定,则仅当请求锁的模式与现有锁的模式相兼容时,才会授予新的锁请求。如果请求锁的模式与现有锁的模式不兼容,则请求新锁的事务将等待释放现有锁或等待锁超时间隔过期。

Popularity: 29% [?]

今天终于把Red5+Hibernate调试通过了,太高兴了

2008年11月13日 admin 1 条评论

太高兴了,现在把源代码贴上来。

Application 代码:

package conjs.invoke;
 
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.IScope;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Application extends ApplicationAdapter implements    IPendingServiceCallback {   
    
private static final Log log = LogFactory.getLog(Application.class);
    
private conjs.game.dao.IConjsUsersDAO ado = new conjs.game.dao.impl.ConjsUsersDAO();
    
    
    @
SuppressWarnings("unchecked")
    @
Override
    
public boolean connect(IConnection conn, IScope scope, Object[] params) {
 
        
if (params == null || params.length == 0) {
            
rejectClient("no pars");
        
}
        
        
        
if (!super.connect(conn, scope, params)) {
            
log.info("super false");
            
return false;
        
}
        
        
log.info("ready.............................................");
    
        
//org.red5.io.utils.ObjectMap<String,String> om = (org.red5.io.utils.ObjectMap)params[0];
        
        
//log.info(om);
        
log.info("params:::::::::::::::::::::::::::::::::::::::"+params[0]);
        
//String username = om.get("name");
        
//String pwd = om.get("pwd");
        
log.info("333333333");
        
    
        
int ii=ado.Exits("aa", "aa");
    
        
if(ii<=0){
            
log.info("usrename and pwd invalidat");
            
System.out.print("..............");
            
return false;
        
}
        
        
return true;
    
}
 
    
    @
Override
    
public void disconnect(IConnection conn, IScope scope) {
        
System.out.println("[disconnect]"+conn.getClient().getId());
        
super.disconnect(conn, scope);
    
}
 
    
public void resultReceived(IPendingServiceCall arg0) {
        
IConnection myConn = Red5.getConnectionLocal();
        
log.info("ID:" + myConn.getClient().getId() + "锟斤拷锟斤拷值:"
                +
arg0.getResult().toString());
    
}
 
 
    
}

 

DAO代码:

public int Exits(String userLogin, String pwd) {
        
Session s = HibernateSessionFactory.getSession();
        
try {
            
String queryString = "from Users as model where model.userid=? and model.pwd=?";
            
Query q  = s.createQuery(queryString);
            
q.setString(0, userLogin);
            
q.setString(1, pwd);
            
int i = q.list().size();
            
log.info("Exits Result:"+i);
            
return i;
        
} catch (RuntimeException re) {
            
throw re;
        
}
        
finally{
            
s.close();
        
}
    
}

前台调用代码就不写了,哈哈

Popularity: 22% [?]

分类: Red5 标签:

Granite Data Services 1.1.0 GA released

2008年11月11日 admin 没有评论

虽然没有用过,但是还是了解一下,据说是Flex DS的开源替代品,呵呵。

下载地址:http://sourceforge.net/project/showfiles.php?group_id=183386

Granite数据服务(Granite Data Services,GDS)是Adobe生命周期数据服务(LiveCycle Data Services)和最近开源的BlazeDS(Blaze Data Services)的一个开源替代品。上周,GDS产品发布了1.0版本,它采用LGPL许可方式。InfoQ.com与GDS项目的创建者Franck Wolff进行了沟通,以了解更多关于该开源项目的信息。

Wolff为InfoQ.com的读者提供了GDS的概述:

GDS是Adobe生命周期数据服务(LiveCycle Data Services)的一个替代品,特别强调与JEE技术的整合,包括众所周知的Java EE持久化系统(比如Ejb3/Hibernate,完全支持懒加载[lazy-loading])。GDS可以让你使用标准的Flex 2及其以上版本的RemoteObjects,它们提供了来自AMF3序列化的全部优点。此外,GDS也为许多技术提供支持:

* 与流行Web框架服务的互操作性
* 调用服务器端的Ejb3会话Bean(无论是否使用JBoss Seam扩展)
* 带有Acegi安全的Spring Beans
* Google Guice服务(加上Warp持久化)
* 支持POJP服务

支持数据推(Data Push)是GDS 1.0的一个新功能。此外,GDS还提供了一个ActionScript3代码生成器(Gas3),它大大加速了Flex应用的开发。GDS和Flex Builder IDE、或者免费的Flex SDK一起,可以为开发人员提供一个完整而强大的Flex应用开发、部署框架。

关于项目现状:

GDS过去比较重要的部分(Ejb3、Spring、Pojo和Gas3)已经被广泛采用,而且生产就绪,这就是我们为什么能直接从0.4跳到1.0版本。目前引进到GDS 1.0中的新功能(Seam、Guice服务、数据推(Data Push))应该会在beta版软件中考虑到。

GDS正由Adequate Systems的两个开发人员(William Draï和我自己)积极开发。此外,由于GDS一年前就公开推出(见GDS文档),所以还有许多来自开源社区的其他人也在为GDS的开发做出贡献。GDS 确定会成为将来基于Flex的解决方案架构的服务器端核心。

关于GDS线路图和RIA架构,Wolff表示:

目前,我们正努力开发一个确保唯一性(每个实体在Flash VM中只存在一个实例)的客户端实体仓库。这个仓库的一个重要功能是当懒关联在Flex端被请求的时候,它们要透明地初始化。某种程度而言,这个功能受到了Cairngorm的启示。

线路图中另一个重要的发展是改进GDS和JBoss Seam的集成。我认为随着RIA新的发展,从架构的角度来看,我们所面临的风险是又回到了15年前客户端/服务器模式(client/server paradigm)占主导地位的状态。这一趋势能带来与无状态服务器相互作用的有状态客户端(例如简单的数据库前端程序)。尽管这个架构对小型Flex应用可能是可行的,但我觉得对大型应用来说,这并不是最好的选择。我想在GDS中继续致力于有状态服务器组件的设想,比如说,就像由Seam对话和任务的设想所定义的一样。

最终的目标是在Flex端建立一个完整的数据管理系统,带有自动表单创建(实体编辑面板)和验证(它在客户端复制Hibernate验证注释)。

Wolff与读者继续分享了GDS中数据推(Data Push)的更多细节:

GDS中的数据推(命名为Gravity)被实现为一种带有通过HTTP发送的AMF3消息、类Comet技术的服务(没有 RTMP、没有特定的因特网 端口),并免费基于Bayeux协议。这种实现对Tomcat 6.0.14及其以上版本、JBoss 4.2.2及其以上版本、Jetty Continuations 6.1.15及其以上版本是可用的。就像Flex文档中描述的一样,Gravity还提供了对JMS适配器的支持。

在客户端代码中,我们不能使用标准的mx.messaging.Consumer和mx.messaging.Producer,因为Consumer类已经从Flex 3 SDK中移除了。所以,我们要实现我们自己的、带有相同属性和方法的ActionScript类Consumer/Producer,不过有一个区别:属性“subtopic”已改名为“topic”(是为了确保Flex 2和Flex 3之间的兼容性)。我们还创建了一个特殊的信道(org.granite.gravity.channels.GravityChannel),必须为了数据推目的地(data push destinations)而在services-config.xml文件中使用它。简而言之,这个信道封装了两个 flash.net.URLStream实例(指令和通道),并支持长轮询(long-polling)传输。

如果你目前正在使用mx.messaging包中的类,你只需要做几个修改即可:

1. 将所有的“mx.messaging.Consumer”imports重命名为“org.granite.gravity.Consumer”(Producer类也一样)。
2. 将所有的“subtopic”重命名为“topic”。
3. 修改services-config.xml中的信道定义。

Wolff还解释说明了一下Gas3的特点:

Gas3的构思是:

1. 通过写Ejb3实体Bean设计数据库模型。
2. 让Gas3生成复制了实体Bean属性的ActionsScript3 Beans(即Flex客户端模型Beans),而且有Hibernate工具生成数据库模式(表和索引的创建)。
3. 用会话Bean、Spring、Guice或Pojo服务写业务逻辑。
4. 写Flex应用(mxml)。

另外,你可以写自己的Gas3代码生成模板,还能完全自定义生成的ActionScript3类。

InfoQ让Wolff比较一下GDS和BlazeDS:

BlazeDS主要是LCDS的一个子集,它不直接提供任何数据管理功能(参见这张图片)。GDS的设计是为了提供与EJB3持久化层的完全整合,并带来一个非常重要而独特的特征(LCDS似乎并不提供):当使用像Hibernate一样的对象/关系持久化工具时,如果你不使用任何懒抓取策略,你可能会面临加载整个数据库的风险。GDS既支持代理(单值关联关系),也为集合支持懒抓取。

此功能基于另一种独特的序列化特点:外部化(Externalizers)。使用标准的Flex AMF3序列化(BlazeDS或LCDS),只有非临时、非静态的公有属性才能被序列化。你不能序列化和持有ActionScript3 Bean中的私有属性,它们应该保留为私有(例如版本号等)。使用BlazeDS或LCDS实现这个目标的唯一方法是把你的实体Bean写成外部化(Externalizable)(但是你必须同时在Java端和AS3端实现稳定的readExternal/writeExternal方法,参见这里)。这是非常繁琐的工作,而且许多源码有潜在的、难以发现的错误(如果你没有实体Bean的源码,它甚至是不可能实现的)。使用GDS外部化,你不用把你的Java Bean写成外部化,你还能让Gas3来生成你的AS3 Bean(强类型的,带有保持私有的私有属性和懒加载支持)。

BlazeDS 文档说BlazeDS有一个“开放适配器架构”,能让你“轻松地集成JMS、EJBs、ColdFusion组件,以及其它数据源”。从这个角度来看,由于GDS也基于一个“开放适配器架构”,所以GraniteDS和BlazeDS并没有很大的不同。开发人员已经编写了Spring、Seam、 Guice服务适配器等。GDS还允许你自定义很多其它的东西,包括控制序列化过程的每个部分、支持特殊类型。

令人惊讶的是,BlazeDS和GDS的数据推实现都基于相同的类Comet架构类型。2007年夏季,GDS在其网站上宣布了这一实现选择,比任何BlazeDS 的宣布都要早很多。因此,除了GDS对Jetty有特别的支持(据我所知,BlazeDS只支持Tomcat)外,数据推的实现可能是非常相似的(BlazeDS的源码还不可获得)。

Wolff提供了一个例子,说明在何处使用GDS会比使用BlazeDS有意义:

如果你是一个使用像Hibernate一样的Java EE持久化技术的软件供应商,你一定会感到支持懒抓取策略的框架的重要性。GDS最重要的特点之一(也是GDS被创建的主要原因之一)就是可能会在客户端使用与Hibernate脫管对象(detached object)一模一样的ActionScript3拷贝,就如同你在一个规范的Java EE应用的Web层一样。使用BlazeDS的话,这似乎是根本不可能的,这意味着你不能用BlazeDS替代GDS。此外,你还可以使用Gas3的代码生成功能,它们能实时保存。

InfoQ向Wolff询问了GDS与BlazeDS项目合并的可能性:

我还没有和Adobe讨论过这个问题。我猜测Adobe还是想保持BlazeDS和LCDS之间清晰的功能分离(在 BlazeDS中没有数据管理)。另一方面,GDS试图给出一个提供缺少功能的替代实现,它基于众所周知的、广泛采用的Java EE技术。目前我唯一可以说的就是,如果Adobe想在BlazeDS中添加GDS的一些或全部特定功能,我一定认为合并是一个合适的选择。但是在这种情况下,对我们来说(我猜还有很多GDS用户),问题是要得到一些保证,保证未来的BlazeDS开发能满足我们的需求。

采访结束时,Wolff对开源社区表示了感谢:

我想再次感谢那些来自开源社区的人们对GDS做出的伟大贡献。

Popularity: 29% [?]

java.sql.SQLException: Positioned Update not supported.

2008年11月1日 admin 没有评论

今天遇到了这个错误:java.sql.SQLException: Positioned Update not supported.

到网上找了很多资料,始终没有解决问题,最近自己解决了,哈哈。

报这个错误的愿意是在含JSON的ACTION里面不能注入其他BEAN,解决方法是在ACTION里面加个excludeProperties并设置他的值就可以了,不多说了,把代码贴上来。

<package name=”ajax” extends=”json-default”>
<action name=”login” class=”LoginAction”>
<result type=”json”>
<param name=”excludeProperties”>
service
</param>

</result>
</action>
</package>

LoginAction是Spring中的BEAN,在这个BEAN中注入的 Service,代码如下:

<bean id=”LoginAction” class=”conjs.blog.action.LoginAction”>
<property name=”service”>
<ref bean=”ConjsUsersService” />
</property>
</bean>

Action中的excludeProperties的值必须要跟这个BEAN注入的值一样(service),否则还是会报 java.sql.SQLException: Positioned Update not supported.这个错误。

Popularity: 21% [?]