随笔 - 4  文章 - 0  评论 - 19 
  2010年2月26日

说起这个rdlc真是害人,网上尽没一篇关于这方面表格设计的文章,害得偶花了两天时间研究了一番(要知道两天时间对于这个项目来说已经是奢侈) 的了 。

为了大家理解,我先简要说一下我们这个表格的设计,以下是这个表格做成后的一个图:

 

相信大家做社保、人力资源等mis系统的时候经常用到这种类型的表格。现在有了vs里的rdlc大家再也不用去花银子买那些昂贵的报表软件了。

现在就说一下设计步骤

1. 新建一个报表,默认名为“Report1.rdlc”

2. 添加一个“列表”,这是最关键的,因为这个报表是打印多条记录(Row),所以必须用这个“列表”作为一个容器,否则以后显示出来的数据就只有一条,在Toolbar上只会看见(1/1页),就因为这个问题偶整了两天。

3. 加入“表”,把“表”拖进“列表”里,这样“表”里的所有字段才能动态显示如“=First(Fields!Student_Address.Value)”,顺便提一下,应该把所有显示的东西全部放到“列表”里。

4. 要想设计成为上图那种表格,需要把“表详细信息”去掉,只留“表格表头”和“表格表尾”,因为在表头和表尾的区域才能嵌入另一个“表”,

5. 设计整理好表格框架,这部份主要是调整表格结构,象上图那些“姓名、性别”这种是用手工敲上去的,“李小华、男”这种是拖放的数据库字段,当然字段是从数据集里拖进来还是数据库里施,这完全取决于你的程序设计,偶这里是从数据集里拖进来的

6.在“列表”的属性里(点列表空白处右键),设置一个分组并设置在结尾处分页,即然是分组那肯定是唯一值,看下图,我选用的是数据库里的自增ID作为分组依据。要不然以后有相同值的时候页数就会错误

 

7. 图像那里有个问题,“表”不支持上下行的合并,这怎么办呢?我只有手动调整图像的位置(用键盘上的上下左右键去移动,配合一下在图像属性里调整Size值),但是在记住,这图像必须是被“列表”包含的,也就是说先把图像托到“例表”内,否则图像不会读取数据,我这里的图像是取的外部URL图像地址。

8. 最后一步就是在winform里加入reprotviewer控件使其绑定到这张报表上。后面的编程就不多说了。

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gxboy/archive/2007/04/20/1572867.aspx

posted @ 2010-02-26 16:35 被诅咒的天才 阅读(1044) 评论(1) 编辑
  2009年11月25日

作者:WinEggDrop 

邮箱中收到几封关于socks5代理编写的信,我也不知道来信者是不是这个论坛的,不过为了省却一个人回复的麻烦,就写个贴子当是全部回复了。

socks5代理和sock4代理都是很相似的(sock4代理网上应该有很多代码,我也曾在这里放过sock4代理的代理),不同的就是sock5代理除了支持UDP协议的数据外,还支持多种验证模式.一般常用的只是无验证模式(NO AUTHENTICATION )和用户/密码模式(USERNAME/PASSWORD),其它模式就算加上了,应用程序也不支持的(你可以看看oicq,msn,flashfxp等软件,也都只是支持这两种模式的).socks5代理一般是三种模式的支持,TCP CONNECT,TCP BIND和UDP ASSOCIATE,这里最常用的是TCP CONNECT,因为绝大部分TCP协议的软件都是使用这种模式的,TCP BIND只会用在FTP的Active模式中(就是数据连接是由FTP服务连接回FTP客户),并不常用,而且我测试过flashfxp和cuteftp,两种都不支持TCP BIND的(就是说如果是用了代理的话,两种软件都不支持使用Active模式,一定要使用Passive模式和FTP服务进行数据交换),所以我们只简单地讨论一下TCP CONNECT和UDP ASSOCIATE两种模式.

Socks5代理的请求和返回信息.
1.客户端发送到socks5代理至少三个字节的请求,第一个字节一定为5,第二个字节为使用多少种验证,第三个字节为验证模式代码.
例:如果要使用"USERNAME/PASSWORD",那么这三个字节为5 1 2

2.Sock5代理接到上面请求后,如果是支持"USERNAME/PASSORD"的验证模式,就会返回两个字节,第一字节为5,第二字节为2.

3.客户端然后就向socks5代理发送验证信息,信息第一字节不需要理会,第二字节为验证用户名的长度,第三字节开始是用户名和密码信息.

4.socks5代理验证用户名和密码成功后,向客户端返回两个字节,5和0,如果验证失败,返回0x05和0xff.

5.客户端开始向sock5代理发送第一个向远程目标进行操作的请求,请求模式如下:
第一位为5
第二位是使用模式,0x01代表TCP CONNECT,0x02代表TCP BIND,0x03代表UDP ASSOCIATE
第三位保留
第四位是地址使用模式:0x01代表IP V4地址;0x03代表域名;0x04代表IP V6地址(一般常见的只是0x01和0x03两种模式,因为很多软件都不支持IP V6的)
第五位开始就是目标的地址和端口.

6.socks代理开始处理这个请求,对于TCP CONNECT和UDP ASSOCIATE模式有不同的处理.
A.对于TCP CONNECT
将请求分析后,将目标地址和 目标端口从请求中解析出来(无论请求中带的地址是否以域名方式发送过来,最终要将地址转换为IPV4的地址),然后使用connect()连接到目标地址中的目标端口中去,如果成功连接,那就向客户端发送回10个字节的信息,第一字节为5,第二字节为0,第三字节为0,第四字节为1,其它字节都为0.
B.对于UDP ASSOCIATE(这个复杂很多了)
将请求分析后,先保存好客户端的连接信息(客户端的IP和连接过来的源端口),然后本地创建一个UDP的socket,并将socket使用bind()绑入本地所有地址中的一个UDP端口中去,然后得到本地UDP绑定的IP和端口,创建一个10个字节的信息,返回给客户端去.第一字节为0x05,第二和第三字节都为0,第四字节为0x01(IPV4地址),第五位到第8位是UDP绑定的IP(以DWORD模式保存),第9位和第10位是UDP绑定的端口(以WORD模式保存).

7.最后是数据的传送了,TCP CONNECT和UDP ASSOCIATE模式又有所不同
A.对于TCP CONNECT
很简单,从客户中读到的所有数据,马上发送到远程目标;从远程目标中读到的所有数据,马上全部发送到客户端
B.对于UDP ASSOCIATE(又是复杂),
有数据包时,首先将数据全部读取,然后判断数据是从客户端还是远程目标传送过来的(在读取时可以得到是从什么地址和端口读取到数据的,然后比较上面第6步时我们保存了下来的客户端的连接信息),如果数据是从客户端读取过来的,我们要将UDP头去掉.例如我们读取到的Buffer,Buffer[3]是1时,UDP头就是10个字节长度,如果Buffer[3]是3的话,UDP头长度是7+Buffer[4].例如我们得到UDP头是20位,我们接收到的Buffer是50位长度,那么我们发送到目标的数据包长度是30位,前20位不发送,只发送后面的30位.如果数据是
从远程目标发送来的,我们就要多发送多10位的UDP头,这10位的UDP头前三位都是0,第四位是0x01,第五到第八位是我们保存下来的客户端的IP,第9和第十位是客户端的端口.如果我们接收到的Buffer长度是50,那么我们发送到客户端的数据就要加上10位的UDP头,也就是一共要发送60位字节长度的数据.

支持验证,支持TCP CONNECT和UDP ASSOCIATE模式的sock5代理的基本编写就是这样。
http://www.faqs.org/rfcs/rfc1928.html 是socks5代理的rfc,不过是写得非常非常简单的。我也有时会质疑rfc为什么都这么简单和模糊,为什么不可以写详细一点,或加上几个简单的例子。FTP服务的rfc甚至连列举文件时,ftp服务向客户发送回去的每一行信息的标准都没有,所以大家可以看到几乎每一个ftp服务向客户端返回的文件列表都不一定是相同的。

有一点需要补充的,那就是socks5代理的超时。在刚连接和验证那段期间可以设置超时,例如用户连接后30秒都没有验证的,就将那连接关闭。但验证后,就不可以设置超时了(或者是可以设置的,但我实在不知道如何做)。不可以设置超时的原因有两个:

1.对于UDP的连接,因为UDP是无连接的,你很难确定用户是否还是连接着,还会继续发送数据过来的。有人说可以定时发送数据过去。这是一种办法,但是要考虑到,因为你不知道用户是使用什么软件在发送UDP数据过来,你乱发数据过去,很大可能是被客户软件认为是不合法的数据而过滤掉,如果sock5代理因为发过去的数据被过滤了而认为客户 是断开了,那么极容易就将没有断开的用户也踢下去了,而且现在的oicq还会使用使用两个连接,一个是UDP连接,另一个是TCP连接,UDP连接只是登陆上服务器时使用,TCP连接却是进行数据传输的,而UDP连接却是一直都不会有数据传输的了,如果socks5代理因为UDP连接长时间没有数据传输而将那个UDP连接关闭的话,oicq也会因为这样而掉线(你关闭了UDP连接,oicq以为代理是不可用了,自己会将TCP连接断开)

2.对于TCP连接,设置超时是很简单,但只是对于一般只是使用一个连接进行数据通讯的软件有效,对于FTP是完全失效。当FTP客户挂socks5代理时,当有数据传输,例如列文件,下载文件或上传文件时,就会需要两个TCP连接,一个是接收FTP客户或接收FTP服务器返回的信息的,另一个是进行数据交换的,如果在进行长时间的数据交换时,例如上传文件或下载文件,有可能是要进行几小时或更长的数据交换,接收FTP客户命令或接收FTP服务器返回信息的那个TCP连接,是一直都没有数据通过的,如果设置了超时,例如1小时没有数据通过就断开连接的话,你就会将那个TCP连接关闭了,如果你关闭了那个TCP连接的话,FTP客户端也会马上将数据交换的那个TCP连接马上关闭(因为FTP客户端会认为自己被断开了)。

就因为这两点,我自己认为无法设置超时.也测试过几个socks5代理软件,也是没有在验证后做超时的处理的。因为TCP连接正常断开还是非正常的断开,socks5代理都可以轻易检查到,但UDP连接就很难检查,所以在测试中都有发现一些不正常断开的UDP连接还是一直没被socks5代理关闭到(ccproxy,wingate,还有大家可能最熟悉的skserver也是这样).

posted @ 2009-11-25 16:05 被诅咒的天才 阅读(352) 评论(1) 编辑
  2009年8月5日
webconfig中的数据库连接是不支持Server.MapPath的,一般我们只能写上数据库文件的物理路径,这给网站迁移带来很大的不方便。今天在网上找到了一个解决办法,与大家分享下。看以下代码:
 
<connectionStrings>
<add name="ConnStr_Access"
     providerName
="System.Data.OleDb"
     connectionString
=
     "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\cms.mdb;"

    
/>
</connectionStrings>


|DataDirectory|会被自动解析到App_Data

下面是MSDN的说明:

 

使用 DataDirectory 替代字符串

AttachDbFileName 已在 ADO.NET 2.0 中进行了扩展,引入了 |DataDirectory|(包含在管道符号中)替代字符串。DataDirectoryAttachDbFileName 结合使用可指示数据文件的相对路径,允许开发人员创建基于数据库源的相对路径(而无需指定完整路径)的连接字符串。

DataDirectory 点的物理位置取决于应用程序的类型。 在此示例中,要附加的 Northwind.mdf 文件位于应用程序的 \app_data 文件夹中。

Data Source=.\\SQLExpress;Integrated Security=true;
User Instance
=true;
AttachDBFilename
=|DataDirectory|\app_data\Northwind.mdf;
Initial Catalog
=Northwind;
使用 DataDirectory 时,目录结构中的结果文件的路径不能高于替代字符串指向的目录。 例如,如果完全展开的 DataDirectory 为 C:\AppDirectory\app_data,则上面显示的示例连接字符串有效,因为它在 c:\AppDirectory 之下。 但是,如果尝试将 DataDirectory 指定为 |DataDirectory|\..\data,将会产生一个错误,因为 \data 不是 \AppDirectory 的子目录。
posted @ 2009-08-05 10:07 被诅咒的天才 阅读(941) 评论(3) 编辑
  2009年2月5日

在实际应用中,我们经常需要用到树型结构功能,数据库结构一般如下

即用一个ParentID来标识该节点从属关系。为了最终生成一棵树,一般做法是把记录选出来,然后在程序里递归重新排好序后再呈现出来,但是如果有大量数据,就带来了性能开销问题。那么能不能直接在数据库利用SQL语句排好树后再输出呢?

SQL2005 有个递归查询功能也就是WITH .. AS 语句。对上面这样的表格使用递归查询,可以查询得到某树支下(包括根)的所有节点记录。类似语句如下:

with RelClass 
as 

select 
* from CMS_Site_Class where ClassID = 1
union all 
select csc.
* from CMS_Site_Class as csc inner join RelClass as rc on csc.ClassID_Parent = rc.ClassID ) 
SELECT 
* from RelClass

将得到ClassID为1的根节点下的所有记录:

但是这个记录集显然没有经过树排序,这时还需要程序里进一步处理才能输出到客户端。在这里我介绍一种WITH 结合 Row_Number() 实现SQL端排序的方法。

先来看看最终的代码:

Code

 

-- =============================================
-- Author:    <kingimg>
-- Create date: <2009-2-5>
-- Description:    <生成已排序的树>
-- =============================================
Create PROCEDURE [dbo].[pCMS_Site_Class__GetList] 
@ClassID 
int 
AS 
BEGIN 
with RelClass 
as 

select 
*,0 as Level,cast('0' as nvarchar(max)) as treepath from CMS_Site_Class where ClassID = @ClassID 
union all 
select csc.
*,rc.[Level] + 1,rc.treepath + dbo.Lpad(Row_Number() over (order by csc.OrderID desc),8as treepath from CMS_Site_Class as csc inner join RelClass as rc on csc.ClassID_Parent = rc.ClassID ) 
SELECT 
* from RelClass order by treepath 
END 

 

执行以上存储过程,最后就输出结果:

这棵树已经从上到下按树结构排好序了!程序里只要原样输出即可!

Lpad函数将指定Int型数据左填0,按指定位数输出。关于为什么要用nvarchar(max)的问题,因为其它固定长度时,在递归查询里的rc.treepath + dbo.Lpad(..)时会改变长度,导致查询错误,使用max长度就避免了这个问题。当然,你也可以用固定长度,相加后再convert回来。

好了,这样子我们就实现了完全SQL端生成已排序的树的目的了,完全脱离了程序处理,这个方法看起来效率还不错呢~

我在此抛砖引玉了,各位如果有可以改进的地方,请贴出来~

posted @ 2009-02-05 12:16 被诅咒的天才 阅读(4738) 评论(14) 编辑