[转载]Sqlite在.NET下的使用和Sqlite数据库清理 - Johnny Li - 博客园

mikel阅读(932)

[转载]Sqlite在.NET下的使用和Sqlite数据库清理 – Johnny Li – 博客园.

SQLite 是一款轻量级的关系型数据库,她的好处我就不详细道来了。本文的初衷是为.net平台的使用者提供帮助。

SQLite有专门为VS2010开发的程序包,大家可以到System.Data.SQLite Download Page 下去下载,注意是:This is the only setup package that is capable of installing the design-time components for Visual Studio 2010. 

安装后,在VS2010中新建数数库链接就会看到有System.Data.SQLite的链接,在这里你可以创建和打开Sqlite数据库:

 

在sqlite链接中,你可以为你的sqlite数据库设置密码和其他配置。确定后,会生成一个没有扩展名的数据文件。

大家一般都了解到,sqlite数据文件是.db或.sqlite或其他扩展结尾,而用VS2010创建的sqlite数据库文件是没有扩展名的,并且其加密能力特别高,一般的sqlite程序在没密码的情况下,很难打开。

用VS2010创建sqlite数据库后,就可以像操作sql server那样操作sqlite,如:建表,查询等都非常方便,感兴趣的可以尝试下,这里就不一一截图说明了。

在项目,需要添加sqlite引用:System.Data.SQLite.dll和System.Data.SQLite.Linq.dll

Sqlite数据库清理

最后,说明下SQLite的一个不好的地方,当数据库中的一个或多个数据表存在大量的插入、更新和删除等操作时,将会有大量的磁盘空间被已删除的数据所占用,在没有执行VACUUM命令之前,SQLite并没有将它们归还于操作系统。

由于该类数据表中的数据存储非常分散,因此在查询时,无法得到更好的批量IO读取效果,从而影响了查询效率。

在SQLite中,仅支持清理当前连接中的主数据库,而不能清理其它Attached数据库。VACUUM命令在完成数据清理时采用了和 PostgreSQL相同的策略,即创建一个和当前数据库文件相同大小的新数据库文件,之后再将该数据库文件中的数据有组织的导入到新文件中,其中已经删 除的数据块将不会被导入,在完成导入后,收缩新数据库文件的尺寸到适当的大小。可以使用VACUUM的方法对sqlite数据库进行清理:

SQLiteConnection sqlconn = new SQLiteConnection(@"Data Source=C:\cache;Version=3;Password=123");
                sqlconn.Open();
                SQLiteCommand sqlCom = sqlconn.CreateCommand();
                sqlCom.CommandText = "VACUUM";
                sqlCom.ExecuteNonQuery();

希望本文对你有所帮助,Thank you!

[转载]百度编辑器图片上传功能解疑 - dreamhappy - 博客园

mikel阅读(1194)

[转载]百度编辑器图片上传功能解疑 – dreamhappy – 博客园.

 项目中使用了百度编辑器ueditor,这里是官网链接,效果还算不错,使用中的一些经验,分享在这里。

我使用的环境是.NET MVC3

最头疼的上传图片问题

ueditor自带了图片上传功能,原理也是使用flash上传。但是我按照官方的配置修改相应的参数后,发现上传出现问题,具体体现在:

本地上传图片,触发上传按钮后,上传失败,代码中提示 Flash插件初始化失败,请更新您的FlashPlayer版本之后重试!,主流浏览器都是这个错误

 

起初我把问题集中在可以看到的错误”提示flash插件初始化错误“,但是这是一个迷惑性的提示,错误的根本原因不在这里。

先看看项目的配置

上传功能是通过Image.html内部的js调用.NET文件夹中的”后台方法“实现的,ueditor内置了一些.net处理逻辑

在排错的过程中,我发现一个问题,上传过程不能调试进入内置的后台方法中,实际上根本原因是,组件中的Uploader类不在整个.NET解决方案的编译范围内

前台上传页面Image.html获取不到后台图片的json信息,导致上传失败。

建议

ueditor内置了一些.net处理逻辑只是为了实现基本的功能,具体项目中这些代码需要集中优化。Uploader文件必须单独提出来编译,才能完成图片上传功能

版本选择和自定义配置

ueditor提供按需下载的功能,但是这个页面有时候会屏蔽,所以还是下载完整版本,开放具体使用的功能,比较科学和安全

由于ueditor是开源编辑器,下载使用时最好记录使用的具体版本和支持语言框架。我们通常最常见的自定义配置是工具栏,而这些配置都是可以按需增减的。

这里的按需增减不仅体现在在全局配置文件中配置,还可以在使用的外围通过js操作配置文件来实现。

1 修改配置项的json数组  window.UEDITOR_CONFIG.toolbars 

2 通过     console.log(window.UEDITOR_CONFIG.toolbars[0]);工具栏配置项

3 增加具体的配置 window.UEDITOR_CONFIG.UserId=100;

通过构造函数,修改其它的配置项

var editor = new baidu.editor.ui.Editor({

pasteplain: true,

imageUrl:””

});

     记得推荐下

暂时写在这里,欢迎大家讨论,如果觉得有帮助,推荐下吧

[转载]正则文本替换器 - trytocatch - 博客园

mikel阅读(983)

[转载][分享]正则文本替换器 – trytocatch – 博客园.

正则表达式,功能很强大,很多稍微专业点的编辑器都提供正则搜索,但在替换功能上,最多提供一个对捕获组的引用(用“\n”来代码第n个捕获组),很多功能都无法实现,要么敲代码,写一个特定程序来完成,要么直接手动修改,简单重复。比如下面的场景。

3*4=?
-6*12=?
9*-5=?
……

如何将问号替换为相乘得到的结果?

因为正则表达式是处理文本的,无法完成数学运算,也不能执行一些编程语言里的方法,比如说判断,也无法生成序列之类的。

解决办法——正则文本替换器

为了解决这些平时碰到的问题,我编写了一个正则文本替换器,替换内容中,允许使用函数表达式,相当于把编程的部分封装了起来,只需要使用简单的表达式就可以完成复杂的替换,并且,实时显示匹配到的内容,和将替换为的内容。

  下面是软件的截图:

  替换表达式的格式为:

$函数名(参数1,参数2,参数3)
$函数名[引用别名](参数1,参数2,参数3)

像上面的问题,使用正则表达式:

((-?\d+)\*(-?\d+)=)\?

和替换表达式:

$(1)$*($(2),$(3))

再执行替换,就完成了。

函数说明:$(n)表示第n个捕获组,$*(n,m)表示n和m和积

如果需要将刚才的替换中,每行加上一个行号,则将替换表达式改成:

$Seq(1,1)、$(1)$*($(2),$(3))

即可生成:

1、3*4=12
2、-6*12=-72
3、9*-5=-45

函数说明:$Seq(n,m)为序列生成器,n表示起始值,m表示步增值。

本替换器不仅能实现四则运算、求模,还可以进行字母大小写转换,进制转换(如16进制转10进制),plSQL里的Nvl、Iif,还有序列生成器等。

  如果这些函数仍满足不了你的需求,还可以自己扩展,添加自己的函数,非常方便。

  软件的帮助菜单里有详细的函数说明、使用帮助,例子,还有添加自定义函数的指导。

下载地址:http://files.cnblogs.com/trytocatch/正则文本替换器.zip

[转载]提高eclipse使用效率 - sw926 - 博客园

mikel阅读(900)

[转载]提高eclipse使用效率 – sw926 – 博客园.

编辑代码常用快捷键

格式化代码的快捷键 Ctrl + Shift + F

格式化缩进的快捷键是 Ctrl + I,只能对选中的文本进行缩进

删除一行的快捷键是 Ctrl + D

当前窗口最大化最小化切换 Ctrl + M

转到最后进行修改的位置 Ctrl + Q

快速查找选中的字符 Ctrl + K(向下) Ctrl + Shift + K(向上)

光标放到一个括号,切换到另一个成对的括号 Ctrl + Shirt + P

在编辑过的位置进行切换 Alt + 左右方向键

阅读代码常用的快捷键

F3不解释(一些人喜欢用Ctrl + 鼠标左键)

选中方法或者变量 Ctrl + Alt + H,查找在哪些地方调用,快速阅读代码和评估代码修改必须要用到的

继承关系 F4,了解代码的框架

快速查找函数和变量 Ctrl + O,输入函数或变量的名字,比在Outline中一个一个找要快很多,但是要对代码有了解

全工程查找 Ctrl + H,代码巨多的情况下必不可少。

由于水平有限,笔者只用到了这些快捷键

如果想知道其他的快捷键 Ctrl + Shift + L

自定义格式化代码

在Preference中打开Java的Format

内建的模版是不能修改的,点击New…,随便输入一个名字,新建一个自己的模板,弹出自定义Edit窗口

可以定义的项目非常丰富,在右边还可以进行预览,就算对英文不感冒,也可以捉摸出大致的意思。对代码进行格式化的好处是不仅仅是美观,便于阅读,在 进行团队开发的时候,使用统一的格式,在合并代码的时候可以避免许多的冲突。修改完成的模版就是使用Ctrl + Shift + F格式化时的模板

自动去除无用的import,自动补全@Override和@deprecated,eclipse的Clean up

在Code Style中,除了Format还有Clean Up

和Format进行同样的操作,新建一个模板,有几个地方我决定有必要改一下

Code Organizing标签选择Remove trailing whitespace(移除尾部的空格)

Organzie imports

选择Organzie imports前效果

import org.model.*;

选择Organzie imports后效果

import org.model.Engine;

切换到Code Style标签

 

Use blocks in if/while/for/do statements if/while/for/do自动添加括号,这个因人而异,我决定即使只用一行,也应该添加括号。

点击菜单里的Source – Clean up,可以对代码进行清理,清理代码最大的好处是——移除没用的import,自动添加@Deprecated和@Override


特别是自动添加@Override,可以很清楚的明白那些函数是继承的。

代码提示

用过visual assistx的一定非常系统它的代码提示功能,我是个没有代码提示就无法Coding的人,点击菜单Windows-Preference,切换到以下窗口

找到Auto Activation,也就是红色方框中的部分,将Auto activation delay(ms): 修改为 50

Auto activation triggers for Java:修改为 .abcdefghigklmnoprstuvwxyz,这样就能随时提示了。

 

最后介绍两个工具,Search Everything 根据文件名快速查找文件,ClipX剪贴板历史记录。

[转载]mysql 性能优化方向 - 孤剑 - 博客园

mikel阅读(1034)

[转载]mysql 性能优化方向 – 孤剑 – 博客园.

按照从大到小,从主要到次要的形式,分析 mySQL 性能优化点,达到最终优化的效果。

利用 mindmanger 整理了思路,形成如下图,每个点在网上都能找到说明,并记录下。形成了优化的思路:

 

1 连接 Connections

经常会遇见”mySQL: error 1040: too many connections”的情况,一种是访问量确实很高,mysql服务器抗不住,这个时候就要考虑增加从服务器分散读压力,另外一种情况是mysql配 置文件中max_connections值过小:

 

mysql> show variables like ‘max_connections‘;

+—————–+——-+

| variable_name    | value |

+—————–+——-+

| max_connections | 256   |

+—————–+——-+

 

这台mysql服务器最大连接数是256,然后查询一下服务器响应的最大连接数:

 

mysql> show global status like ‘max_used_connections‘;

 

mysql服务器过去的最大连接数是245,没有达到服务器连接数上限256,应该没有出现1040错误,比较理想的设置是

 

max_used_connections / max_connections * 100% ≈ 85%

 

最大连接数占上限连接数的85%左右,如果发现比例在10%以下,mysql服务器连接数上限设置的过高了。

1.1 max_connections

1.2 Max_used_connections

2  线程 Thread

mysql> show global status like ‘thread%‘;

+——————-+——-+

| variable_name      | value |

+——————-+——-+

| threads_cached     | 46     |

| threads_connected | 2      |

| threads_created    | 570    |

| threads_running    | 1      |

+——————-+——-+

 

如果我们在mysql服务器配置文件中设置了thread_cache_size,当客户端断开之后,服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)。

threads_created表示创建过的线程数,如果发现threads_created值过大的话,表明mysql服务器一直在创建线程,这 也是比较耗资源,可以适当增加配置文件中thread_cache_size值,查询服务器thread_cache_size配置:

 

mysql> show variables like ‘thread_cache_size‘;

+——————-+——-+

| variable_name      | value |

+——————-+——-+

| thread_cache_size | 64     |

+——————-+——-+

 

示例中的服务器还是挺健康的。

2.1 thread_cache_size

2.2 thread_cached

2.3 thread_created

3  缓存 cache

3.1 文件打开数

mysql> show global status like ‘open_files‘;

+—————+——-+

| variable_name | value |

+—————+——-+

| open_files     | 1410  |

+—————+——-+

 

mysql> show variables like ‘open_files_limit‘;

+——————+——-+

| variable_name     | value |

+——————+——-+

| open_files_limit | 4590  |

+——————+——-+

 

比较合适的设置:open_files / open_files_limit * 100% <= 75%

3.1.1 open_files

3.1.2 open_files_limit

3.2 数据表

3.2.1 打开数 open_tables

mysql> show global status like ‘open%tables%‘;

+—————+——-+

| variable_name | value |

+—————+——-+

| open_tables    | 919    |

| opened_tables | 1951  |

+—————+——-+

 

open_tables表示打开表的数量,opened_tables表示打开过的表数量,如果opened_tables数量过大,说明配置中 table_cache(5.1.3之后这个值叫做table_open_cache)值可能太小,我们查询一下服务器table_cache值:

 

mysql> show variables like ‘table_cache‘;

+—————+——-+

| variable_name | value |

+—————+——-+

| table_cache    | 2048  |

+—————+——-+

 

比较合适的值为:

 

open_tables / opened_tables * 100% >= 85%

 

open_tables / table_cache * 100% <= 95%

 

open_tables

opend_tables

open_table_cache

3.2.2 临时表 tmp_table

mysql> show global status like ‘created_tmp%‘;

+————————-+———+

| variable_name      | value    |

+————————-+———+

| created_tmp_disk_tables | 21197    |

| created_tmp_files    | 58       |

| created_tmp_tables    | 1771587 |

+————————-+———+

 

每次创建临时表,created_tmp_tables增加,如果是在磁盘上创建临时表,created_tmp_disk_tables也增加,created_tmp_files表示mysql服务创建的临时文件文件数,比较理想的配置是:

 

created_tmp_disk_tables / created_tmp_tables * 100% <= 25%

 

比如上面的服务器 created_tmp_disk_tables / created_tmp_tables * 100% = 1.20%,应该相当好了。我们再看一下mysql服务器对临时表的配置:

 

mysql> show variables where variable_name in (‘tmp_table_size‘, ‘max_heap_table_size‘);

+———————+———–+

| variable_name    | value      |

+———————+———–+

| max_heap_table_size | 268435456 |

| tmp_table_size    | 536870912 |

+———————+———–+

 

只有256mb以下的临时表才能全部放内存,超过的就会用到硬盘临时表。

created_tmp_tables

memory 中存储

disk 中存储

created_tmp_disk_tabls

磁盘文件

created_tmp_files

See also: open_files

3.2.3 表锁情况

mysql> show global status like ‘table_locks%‘;

+———————–+———–+

| variable_name          | value      |

+———————–+———–+

| table_locks_immediate | 490206328 |

| table_locks_waited     | 2084912    |

+———————–+———–+

 

table_locks_immediate 表示立即释放表锁数,

 

table_locks_waited 表示需要等待的表锁数,

 

如果 table_locks_immediate / table_locks_waited > 5000,最好采用innodb引擎,因为innodb是行锁而myisam是表锁,对于高并发写入的应用innodb效果会好些。

 

示例中的服务器 table_locks_immediate / table_locks_waited = 235,myisam就足够了。

table_locks_immediate

table_locks_waited

3.2.4 表扫描情况

See also: read_buffer_size

mysql> show global status like ‘handler_read%‘;

+———————–+————-+

| variable_name          | value        |

+———————–+————-+

| handler_read_first     | 5803750      |

| handler_read_key       | 6049319850  |

| handler_read_next      | 94440908210 |

| handler_read_prev      | 34822001724 |

| handler_read_rnd       | 405482605    |

| handler_read_rnd_next | 18912877839 |

+———————–+————-+

 

各字段解释参见 http://hi.baidu.com/thinkinginlamp/blog/item/31690cd7c4bc5cdaa144df9c.html ,调出服务器完成的查询请求次数:

 

mysql> show global status like ‘com_select‘;

+—————+———–+

| variable_name | value      |

+—————+———–+

| com_select     | 222693559 |

+—————+———–+

 

计算表扫描率:

 

表扫描率 = handler_read_rnd_next / com_select

 

如果表扫描率超过 4000,说明进行了太多表扫描,很有可能索引没有建好,增加 read_buffer_size 值会有一些好处,但最好不要超过8mb。

handler_read_rnd_next

com_select

3.3 key_buffer_size

key_buffer_size是对myisam表性能影响最大的一个参数,下面一台以myisam为主要存储引擎服务器的配置:

 

mysql> show variables like ‘key_buffer_size‘;

 

+—————–+————+

| variable_name    | value       |

+—————–+————+

| key_buffer_size | 536870912 |

+—————–+————+

 

分配了 512mb 内存给 key_buffer_size ,我们再看一下 key_buffer_size 的使用情况:

 

mysql> show global status like ‘key_read%‘;

+————————+————-+

| variable_name     | value     |

+————————+————-+

| key_read_requests   | 27813678764 |

| key_reads       | 6798830      |

+————————+————-+

 

一共有27813678764个索引读取请求,有6798830个请求在内存中没有找到直接从硬盘读取索引,计算索引未命中缓存的概率:

 

key_cache_miss_rate = key_reads / key_read_requests * 100%

 

比如上面的数据,key_cache_miss_rate为0.0244%,4000个索引读取请求才有一个直接读硬盘,已经很bt 了,key_cache_miss_rate在0.1%以下都很好(每1000个请求有一个直接读硬盘),如果key_cache_miss_rate在 0.01%以下的话,key_buffer_size分配的过多,可以适当减少。

 

【注意】key_read_buffer 默认值为 8M 。在专有的数据库服务器上,该值可设置为 RAM * 1/4

 

mysql服务器还提供了key_blocks_*参数:

 

mysql> show global status like ‘key_blocks_u%‘;

+————————+————-+

| variable_name           | value        |

+————————+————-+

| key_blocks_unused       | 0            |

| key_blocks_used         | 413543       |

+————————+————-+

 

key_blocks_unused表示未使用的缓存簇(blocks)数,key_blocks_used表示曾经用到的最大的blocks数, 比如这台服务器,所有的缓存都用到了,要么增加key_buffer_size,要么就是过渡索引了,把缓存占满了。比较理想的设置:

 

key_blocks_used / (key_blocks_unused + key_blocks_used) * 100% ≈ 80%

3.3.1 key_reads

3.3.2 key_read_requests

3.3.3 Key_block_unused

3.3.4 key_block_used

3.4 排序使用情况 sort_buffer

mysql> show global status like ‘sort%‘;

+——————-+————+

| variable_name      | value       |

+——————-+————+

| sort_merge_passes | 29          |

| sort_range         | 37432840    |

| sort_rows          | 9178691532 |

| sort_scan          | 1860569     |

+——————-+————+

 

sort_merge_passes 包括两步。mysql 首先会尝试在内存中做排序,使用的内存大小由系统变量 sort_buffer_size 决定,如果它的大小不够把所有的记录都读到内存中,mysql 就会把每次在内存中排序的结果存到临时文件中,等 mysql 找到所有记录之后,再把临时文件中的记录做一次排序。这再次排序就会增加 sort_merge_passes。实际上,mysql 会用另一个临时文件来存再次排序的结果,所以通常会看到 sort_merge_passes 增加的数值是建临时文件数的两倍。因为用到了临时文件,所以速度可能会比较慢,增加 sort_buffer_size 会减少 sort_merge_passes 和 创建临时文件的次数。但盲目的增加 sort_buffer_size 并不一定能提高速度,见 how fast can you sort data with mysql?(引自http://qroom.blogspot.com/2007/09/mysql-select-sort.html,貌似被墙)

 

另外,增加read_rnd_buffer_size(3.2.3是record_rnd_buffer_size)的值对排序的操作也有一点的好 处,参见:http://www.mysqlperformanceblog.com/2007/07/24/what-exactly-is- read_rnd_buffer_size/

3.4.1 sort_buffer_size

3.4.2 sort_merge_passes

See also: created_tmp_files

3.5 查询缓存

mysql> show global status like ‘qcache%‘;

+————————-+———–+

| variable_name            | value      |

+————————-+———–+

| qcache_free_blocks       | 22756      |

| qcache_free_memory       | 76764704  |

| qcache_hits              | 213028692 |

| qcache_inserts           | 208894227 |

| qcache_lowmem_prunes     | 4010916    |

| qcache_not_cached        | 13385031  |

| qcache_queries_in_cache | 43560      |

| qcache_total_blocks      | 111212     |

+————————-+———–+

 

mysql查询缓存变量解释:

 

qcache_free_blocks:缓存中相邻内存块的个数。数目大说明可能有碎片。flush query cache会对缓存中的碎片进行整理,从而得到一个空闲块。

 

qcache_free_memory:缓存中的空闲内存。

 

qcache_hits:每次查询在缓存中命中时就增大

 

qcache_inserts:每次插入一个查询时就增大。命中次数除以插入次数就是命中比率。

 

qcache_lowmem_prunes:缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看;如果这个 数字在不断增长,就表示可能碎片非常严重,或者内存很少。(上面的 free_blocks和free_memory可以告诉您属于哪种情况)

 

qcache_not_cached:不适合进行缓存的查询的数量,通常是由于这些查询不是 select 语句或者用了now()之类的函数。

 

qcache_queries_in_cache:当前缓存的查询(和响应)的数量。

 

qcache_total_blocks:缓存中块的数量。

 

 

我们再查询一下服务器关于query_cache的配置:

 

mysql> show variables like ‘query_cache%‘;

+——————————+———–+

| variable_name                 | value      |

+——————————+———–+

| query_cache_limit             | 2097152    |

| query_cache_min_res_unit      | 4096       |

| query_cache_size              | 203423744 |

| query_cache_type              | on         |

| query_cache_wlock_invalidate | off        |

+——————————+———–+

 

各字段的解释:

 

query_cache_limit:超过此大小的查询将不缓存

 

query_cache_min_res_unit:缓存块的最小大小

 

query_cache_size:查询缓存大小

 

query_cache_type:缓存类型,决定缓存什么样的查询,示例中表示不缓存 select sql_no_cache 查询

 

query_cache_wlock_invalidate:当有其他客户端正在对myisam表进行写操作时,如果查询在query cache中,是否返回cache结果还是等写操作完成再读表获取结果。

 

query_cache_min_res_unit的配置是一柄”双刃剑”,默认是4kb,设置值大对大数据查询有好处,但如果你的查询都是小数据查询,就容易造成内存碎片和浪费。

 

查询缓存碎片率 = qcache_free_blocks / qcache_total_blocks * 100%

 

如果查询缓存碎片率超过20%,可以用flush query cache整理缓存碎片,或者试试减小query_cache_min_res_unit,如果你的查询都是小数据量的话。

 

查询缓存利用率 = (query_cache_size – qcache_free_memory) / query_cache_size * 100%

 

查询缓存利用率在25%以下的话说明query_cache_size设置的过大,可适当减小;查询缓存利用率在80%以上而且qcache_lowmem_prunes > 50的话说明query_cache_size可能有点小,要不就是碎片太多。

 

查询缓存命中率 = (qcache_hits – qcache_inserts) / qcache_hits * 100%

 

示例服务器 查询缓存碎片率 = 20.46%,查询缓存利用率 = 62.26%,查询缓存命中率 = 1.94%,命中率很差,可能写操作比较频繁吧,而且可能有些碎片。

3.5.1 qcache_free_blocks

3.5.2 qcache_free_memory

3.5.3 qcache_hits

3.5.4 qcache_lowmem_prunes

3.5.5 qcache_queries_in_cache

3.5.6 qcache_not_cached

3.5.7 qcache_total_blocks

4 其他

4.1 read_buffer_size

4.2 慢查询

mysql> show variables like ‘%slow%‘;

+——————+——-+

| variable_name     | value |

+——————+——-+

| log_slow_queries | on     |

| slow_launch_time | 2      |

+——————+——-+

 

mysql> show global status like ‘%slow%‘;

+———————+——-+

| variable_name    | value |

+———————+——-+

| slow_launch_threads | 0    |

| slow_queries    | 4148  |

+———————+——-+

 

配置中打开了记录慢查询,执行时间超过2秒的即为慢查询,系统显示有4148个慢查询,你可以分析慢查询日志,找出有问题的sql语句,慢查询时间 不宜设置过长,否则意义不大,最好在5秒以内,如果你需要微秒级别的慢查询,可以考虑给mysql打补丁:http://www.percona.com /docs/wiki/release:start,记得找对应的版本。

 

打开慢查询日志可能会对系统性能有一点点影响,如果你的mysql是主-从结构,可以考虑打开其中一台从服务器的慢查询日志,这样既可以监控慢查询,对系统性能影响又小。

 完整说明及文件下载

[转载]我的软件用了那些技术 - Sam Xiao - 博客园

mikel阅读(1041)

[转载]我的软件用了那些技术 – Sam Xiao – 博客园.

好多技术人员都有一个通病,不关注用户的需求,产品的可用性,只看使用的技术的新不新,潮不潮,这就是所谓的技术发烧友。

这段时间,断断续续的开发一个WPF的软件,也拿出来Show一下。要不放在硬盘里就发霉了。

热点一:SOA的分布式理念

现在的开发理念,不管是企业级的ERP,还是网站式的应用,都涉及到了SOA的分布式。就拿一个比较典型的网站来说吧,做网站的童鞋们对 CAS,SSO这些关键字并不陌生吧,实质就是应用了SOA的理念,把一个网站平台的认证授权单独抽取出来独立成一个系统,其它业务网站的认证授权都以这 个为基础,实现了单点的登录,授权。其实在企业级的ERP中,我们也是这么干的,我们把认证授权提取成一个独立的基础平台(这个甚而平台有可能包括:公共 基础数据系统,消息系统,工作流,报表)的一个子系统,其它业务系统都围绕着这个基础平台进行开发。如下图所示,把每个业务系统的权限都提取出来,放在基 础平台。

因为这是一个基础开发平台,所以必须为别的应用程序留下服务接口,方便的与别的应用程序通信,实现其软件的价值。

热点二:WCF的安全机制(拦截器)

我们把通用的功能都提取出来组成了一个基础开发平台,以后的业务系统都只关心业务固然是好。不过有点乌托邦了。你想想,业务系统与基础系统怎样通 信?怎和样保证通信的安全,这个问题曾经困扰了我好久。系统之间的通信,大家不约而同的可能都想到了Web Service或者WCF吧,不过怎样保证Web Service,WCF的安全呢?我还看到过有人用JavaScript来调用web Service(Web Service做的是CRUD的操作),这是把自己的衣服脱了赤裸裸的让别人来攻击,给我吓出了一身冷汗呀!

那我们怎样来保证Web Service 或者WCF的安全呢?最笨的方法可以为每个WCF或者Web Service定义两个参数(一个用户名,一个加密码的密码), 或者再改进一下定义一个Token的参数(这个方法我这样做过,鄙视自己一下),有的为了代码看起来更优雅一些,在请求服务时把这个Token写在 Header里。然后在执行Web Service 或者  WCF的主体之前,根据传过来的参数在数据库里查询一下,判断这个请求是否有权限。不过一些中大型的系统,一般都会有上百甚至几千个Web Service,每个服务都定义一个参数,或者在Header里定义一个键值对,是不是显得代码很臃肿呢?我们针对这样的问题,我们采用WCF特别的机制 拦截器。 WCF中的拦截器其实就是AOP的一个实现,当然这个实现我们也可以自己来写。

在调用每个Web Service或者WCF之前,我都加一个Token在Header里,这个动作,我们完全可以公用,就是采用AOP技术。

在公共基础平台接收到请求的时候,同样可以用AOP的技术,判断Token是否有效。具全实现看源码。

热点三:WPF

在bs结构的系统中,HTML5的UI比较有前景,在cs结构的UI中,我想WPF应该有她独特的优势,在这儿我们暂时不讨论平台的好坏,技术优劣。且看我怎样用WPF来实现一个软件的UI。

1)个性化的菜单:

2)炫耀的表单验证

3)自定义,动态生成xaml的模板

4)目前正在用mvvmlight改写原有的代码。

这些亮点都不得不让我用WPF,这是一个技术爱好者的执着追求,是我的理念。

热点四:Code First

我们什么SOA, AOP, IOC等热点技术都用上了,千万不要拉下了ORM,ORM有Ibatis, hibernate,daper等,但是从性能,可使用性上来说各有千秋,没有优劣,但是我感觉在.net平台上,只有entity framework才是真正的可用orm。entity framework有三种模式,mode first, database first, code first。我为什么在这个项目中选择code first是有原因的。因为我定义的实体,既想作为生成数据库的定义,又想作为WCF中数据传输的数据契约。往往单方面从一个技术角度来看并不难,但是技术与技术叠加,就会出现很多稀奇的问题。我上一段代码片段:

其中红色的是WCF数据契约的标识,蓝色的是Code First的数据定义。把这两种定义都集中在Model上,减少了业务层代码,业务层重点放在了处理业务上。

 

总结:

此软件在用户操作体验,代码结构上都有待改进的地方,在上文的介绍中,你对某个东西感兴趣可以在博客园发短消息联系我,一起探讨,共同进步。

如果想获取源码,可以请我喝一杯,毕竟辛苦了好久,支持我一下。^_^  源码下载

[转载]经验分享:10个简单实用的 jQuery 代码片段 - 梦想天空(山边小溪) - 博客园

mikel阅读(846)

[转载]经验分享:10个简单实用的 jQuery 代码片段 – 梦想天空(山边小溪) – 博客园.

平滑滚动到锚点

这个功能很常见,在网站底部添加一个让访客快速回到页面顶部的功能,下面是实现这个功能的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// HTML:
// <h1 id="anchor">Lorem Ipsum</h1>
// <p><a href="#anchor" class="topLink">Back to Top</a></p>
$(document).ready(function() {
    $("a.topLink").click(function() {
        $("html, body").animate({
            scrollTop: $($(this).attr("href")).offset().top + "px"
        }, {
            duration: 500,
            easing: "swing"
        });
        return false;
    });
});

缩放图片

虽然图片应该在服务器端缩放,不过如果服务器端未做缩放,需要再客户端缩放的时候,可以使用下面这个方便的代码片段:

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
$(window).bind("load", function() {
    // IMAGE RESIZE
    $('#product_cat_list img').each(function() {
        var maxWidth = 120;
        var maxHeight = 120;
        var ratio = 0;
        var width = $(this).width();
        var height = $(this).height();
    
        if(width > maxWidth){
            ratio = maxWidth / width;
            $(this).css("width", maxWidth);
            $(this).css("height", height * ratio);
            height = height * ratio;
        }
        var width = $(this).width();
        var height = $(this).height();
        if(height > maxHeight){
            ratio = maxHeight / height;
            $(this).css("height", maxHeight);
            $(this).css("width", width * ratio);
            width = width * ratio;
        }
    });
    //$("#contentpage img").show();
    // IMAGE RESIZE
});

滚动时自动加载内容

很多网站使用了流行的瀑布图布局,这种类型的网站在页面滚动的时候会自动加载内容。下面这段代码让你能够把这个功能搬到你的网站上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var loading = false;
$(window).scroll(function(){
    if((($(window).scrollTop()+$(window).height())+250)>=$(document).height()){
        if(loading == false){
            loading = true;
            $('#loadingbar').css("display","block");
            $.get("load.php?start="+$('#loaded_max').val(), function(loaded){
                $('body').append(loaded);
                $('#loaded_max').val(parseInt($('#loaded_max').val())+50);
                $('#loadingbar').css("display","none");
                loading = false;
            });
        }
    }
});
$(document).ready(function() {
    $('#loaded_max').val(50);
});

检测密码强度

在表单功能中,经常会有检测用户输入的密码强度的功能,下面这个代码片段使用正则表达式来检测密码是否足够安全,当然记得在服务端也进行表单验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$('#pass').keyup(function(e) {
     var strongRegex = new RegExp("^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\W).*$", "g");
     var mediumRegex = new RegExp("^(?=.{7,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$", "g");
     var enoughRegex = new RegExp("(?=.{6,}).*", "g");
     if (false == enoughRegex.test($(this).val())) {
             $('#passstrength').html('More Characters');
     } else if (strongRegex.test($(this).val())) {
             $('#passstrength').className = 'ok';
             $('#passstrength').html('Strong!');
     } else if (mediumRegex.test($(this).val())) {
             $('#passstrength').className = 'alert';
             $('#passstrength').html('Medium!');
     } else {
             $('#passstrength').className = 'error';
             $('#passstrength').html('Weak!');
     }
     return true;
});

均衡元素的高度

使用纯 CSS代码实现均衡元素的高度比较困难,而下面这段 JQuery 代码会根据最高的元素来均衡所有的 Div 元素。

1
2
3
4
5
6
7
var maxHeight = 0;
$("div").each(function(){
   if ($(this).height() > maxHeight) { maxHeight = $(this).height(); }
});
$("div").height(maxHeight);

修复 IE6 PNG 问题

至今,IE6 在国内仍然占据了大量的份额,因此在 Web 开发中仍然需要考虑 IE6 的兼容问题。比较常用的 IE6 PNG 图片问题,下面这段代码可以方便的修复。

1
2
3
4
5
$('.pngfix').each( function() {
   $(this).attr('writing-mode', 'tb-rl');
   $(this).css('background-image', 'none');
   $(this).css( 'filter', 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="path/to/image.png",sizingMethod="scale")');
});

解析 JSON 字符串

使用 JQuery 解析 JSON 数据并不复杂。下面是一个高效解析 JSON 数据并将其追加到您的网页的例子。

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
function parseJson(){
    //Start by calling the json object, I will be using a
        //file from my own site for the tutorial
    //Then we declare a callback function to process the data
    $.getJSON('hcj.json',getPosts);
 
    //The process function, I am going to get the title,
        //url and excerpt for 5 latest posts
    function getPosts(data){
        //Start a for loop with a limit of 5
        for(var i = 0; i < 5; i++){
            var strPost = '<h2>'
                      + data.posts[i].title
                      + '</h2>'
                      + '<p>'
                      + data.posts[i].excerpt
                      + '</p>'
                      + '<a href="'
                      + data.posts[i].url
                      + '" title="Read '
                      + data.posts[i].title
                      + '">Read ></a>';
            //Append the body with the string
            $('body').append(strPost);
        }
    }
}
 
//Fire off the function in your document ready
$(document).ready(function(){
    parseJson();                  
});

隔行换色

这是一个很老的功能了,在大的列表或表格中,隔行颜色可以大大提高内容的可读性。下面的代码可以非常简单实现这个功能。

$('div:odd').css("background-color", "#F4F4F8");
$('div:even').css("background-color", "#EFF1F1");

预加载图片

你是否注意到 facebook 相册的图片加载速度特别快?那是因为在你看到这些图片之前已经预加载到你的浏览器缓存中了。下面是实现这个类似功能的代码示例:

1
2
3
4
5
6
7
8
var nextimage = "/images/some-image.jpg";
$(document).ready(function(){
    window.setTimeout(function(){
        var img = $("<img>").attr("src", nextimage).load(function(){
            //all done
        });
    }, 100);
});

让整个 Div 可点击

这是实现链接的父 Div 也能够点击的简单方法,HTML 示例代码如下:

1
2
3
4
<div class="myBox">
     blah blah blah.
    <a href="http://google.com">link</a>
</div>

下面的 JQuery 代码让整个 Div 可点击:

1
2
3
4
$(".myBox").click(function(){
     window.location=$(this).find("a").attr("href");
     return false;
});

[转载]浅谈Excel开发:一 Excel 开发概述 - yangecnu - 博客园

mikel阅读(846)

[转载]浅谈Excel开发:一 Excel 开发概述 – yangecnu – 博客园.

    做Office相关的开发工作快一年多了,在这一年多里,在插件的开发中遇到了各种各样的问题和困难,还好同事们都很厉害,在和他们的交流讨论中学到了很 多的知识。目前Office相关的开发资料是比较少的,最最开始的时候,我看的是一本英文资料,然后再就是MSDN上面去提问了。所以我想写一点东西,让 大家也少走一些弯路。

这篇文章就简要介绍一下Office开发的一些相关的知识,使大家对这个有一个大体的了解。

首先来看一看Office 的开发方式。

一 Office开发方式

1 VBA (Visual Basic Application)

VBA是一种Visual Basic的宏语言,它应该是最早的Office提供定制化的一种解决方案,在1994年发行的Excel 5.0版本中,就具备了VBA的宏功能。从名字上似乎可以看出他是VB的一个子集,和Visual Basic不同,VBA是一种宿主型语言。由于那个时候Visual Basic非常火, VBA取得了很大的成功,无论是专业的开发人员,还是刚入门的非开发人员,都可以利用VBA完成简单或复杂的需求。现在在一些办公环境中,VBA用的非常 多,比如国内比较著名的ExcelHome论坛,上面就有很多关于Excel VBA的讨论,而且VBA还能够调研Com组件里面的一些方法,在其他的Office开放方式中,如VSTO或者SharedAddin中,VBA有时候 可以辅助完成某些功能,如RTD函数,UDF函数的调用,专用模板的开发,动画效果的演示等等。不光是Office,有很多其他的软件业比如比较有名的 ArcGIS,CorelDraw等软件,都提供了VBA的定制化解决方案。

Excel VBA

但是他也有很多缺点。VBA本身拥有很多的局限性,比如缺少一些常用的类型,调试起来不方便,VB语言虽然简单,但是现在又很多的开发者都使用的 是.NET,VB的一些语法可能很多人不适应。再就是VBA是一种脚本类型的解释型的语言,在安全性比如源代码容易被破解,就像JavaScript保密 性不好一样,在执行效率方面没有一些编译型解决方案来的快。举个例子,比如说,我们可以把我们的自定义函数使用VBA来编写,然后存储为.xla文件,这 样在Excel中就可以调用我们的这些函数了。但是由于VBA是解释型的语言,就像JavaScript那样,每次运行都要边解释边运行,而不是像其他一 些语言,在编译成二进制后,就能直接加载运行。所以可以将我们的自定义函数写到类库然后注册,或者直接使用C++,将函数写到xll中,这样效率和安全性 方面要比VBA方式要好,这里只是稍微提一下,后面的文章会详细介绍。

2 Shared Addin

SharedAddin,就像Visual Studio可以外接插件一样,也可以使用一些技术为Office开发一些插件。对VBA的一些问题,一些专业的开发人员,可以使用 VisualBasic或者VisualC++等工具来引用Office的一些dll,来针对Office进行开发。开发的时候将dll注册为com组 件,并在注册表里面进行注册,这样就可以在Office里面直接调用这些插件了。

Com Addin方式基本上解决了VBA存在的安全性及效率低的问题,但是他要求的门槛比较高,即使是专业的开发人员也不一定能够很好的掌握。Com Addin还有一个优点是,使用这个开发能够弥补VSTO在某些版本尚不支持的尴尬,比如VSTO的Ribbon菜单在07以下版本中就不能支持,并且在 1.0版本下不支持Application Level级别的开发。使用Com Addin开发,能够使得插件可以具有较好的兼容性。

GeodesiX是一个地理信息Excel插件,他能够将在Excel中与GoogleMap进行交互,比如绘制专题图,进行缓冲区分析,叠加,图示邮递员问题等等。

geodix showrouteonmap

Travelling Salesman problem

3 VSTO (Visual Studio Tools for Office)

2000年微软发布了.NET平台战略之后,推出了一系列运行在.NET上新语言如C#和VB.NET。在这种情况下,开发者能够使用.NET 平台上的语言来开发Office。 从Office 2003开始,微软推出了VSTO 1.0。VSTO主要是对Office的一些dll进行了.NET封装,使得我们可以使用.NET上的语言来方便的对Office的一些方法进行调用。所 以,Office开发跨入了一个新的时代,开发人员可以使用更加高级的语言和熟悉的技术来更容易的进行Office开发。VSTO 1.0是伴随着.NET 1.0平台推出的,支持Office 03以上的所有版本。

对于企业及的应用和开发,VSTO或许是首要选择,他极大地扩展了Office应用程序的能力,使用.NET平台支持的编程语言,能够直接访问.NET上面众多的类库。具有较好的安全机制。简化了Office插件的开发和部署。

VSTO也有一些缺点,比较明显的是他依赖于.NET 平台,在部署的时候,可能需要在目标机器上安装.NET Framework框架,再者就是版本的兼容性,没有哪一个VSTO版本能够兼容所有的Office版本。

下面是VSTO的各个版本及对应的支持的.NET平台以及对各Office版本的支持。

VSTO VERSION

 

以上图表在 http://en.wikipedia.org/wiki/Visual_Studio_Tools_for_Office 的基础上进行了修改

提到VSTO,有一个比较重要的问题就是Document Level 还是Application Level程序,在创建VSTO应用程序的时候,就必须进行选择。就像名称所说的那样,Document level就是指对单个Word或者Excel文档进行自定义开发,该文件打开时,就加载,关闭时就卸载。如果是Application Level级别的,就是对应用程序中所有打开的文档实例都能够起作用,应用程序加载时插件加载,应用程序关闭时插件卸载。

SharedAdd和VSTO两者很多人都弄不清楚,他俩既有相同的地方也有不同点,关于这一点Cindy Meister大神有详尽的比较,异同点有:

相同点:

  1. 他 们都会在操作系统的注册表中进行注册,比如对于Excel应用程序来说,会在HKCU\Software\Microsoft\Office\Excel \Addins这个下面创建注册表项,当应用程序比如Excel加载时,会逐一加载这个下面注册的插件.这些插件在COM加载项中可以进行集中管理。
  2. 他们都在Office Com接口上面通过Office对象模型进行构建,他们都可以将建一些可扩展的UI,比如用户自定义任务面板(Custom task panel),Ribbon菜单等。

不同点:他们也有很多不同点,主要不同点如下:

  1. 从 名字可以看出Shared Add-In可以在多个不同的Office应用程序之间,比如Excel,Word中共享。因此在Shared Add-in中需要一些判断和处理不同宿主程序的代码。但是VSTO Add-Ins则是应用程序明确的。VSTO Add-Ins只能用在一种宿主应用程序中如Excel或者Word中运行,因此不需要在代码中处理对不同的宿主应用程序的类型做特殊的处理,比如将通用 的对象转换为特定的对象,通过反射等调用不同应用程序的方法等。
  2. 要在Shared Add-In中创建特殊的UI界面,如Ribbon菜单,Custom Task Panel以及Form窗体等,需要实现office.dll中的三个接 口:Office.IRibbonExtensibility,Office.ICustomTaskPanelConsumer及 Outlook.FormRegionStartup接口。不论是创建的是以上哪种类型的UI界面,我们都需要在接口方法中编写很多处理代码。但是,如果 使用Visual Studio Tools for Office,这些东西VSTO都帮我们包装好了,我们只需要从工具箱中往界面上拖动添加新的Ribbon菜单,UserControl,及 FormRegion即可。这些界面在Visual Studio中都提供了设计时支持,我们只需要拖动,设置熟悉,双击然后处理绑定的事件即可,就象设计Windows Form应用程序一样简单。
  3. 还 有一个重要的区别是安全模型。对于SharedAddin的IDTExtensibility2接口来说,从来不需要代码的安全访问机制(CAS),因 此,在Office加载SharedAddin的时候,不需要调用caspol.exe方法来为Addin的程序集授予完全信任的权限。在VSTO 中,2008版本中使用了.NET的安全策略,但是VSTO 2008使用了ClickOne部署以及真实代码模型(Authenticode)
  4. VSTO为每一个VSTO Add-Ins创建了一个AppDomain,因此各个Addin之间互不影响,开发者不需要担心一些诸如“Outlook关闭不了”的问题。当写在VSTO Addin的时候,AppDomian也会被卸载,CLR会卸载与其相关的所有资源。
  5. VSTO默认安装在HKCU(Current User)下面,而SharedAddin则默认部署到HKLM(Local Machine)下面。如果想让我们开发的VSTO Addin能让所有人使用,则需要在部署的时候对注册表进行一些额外的手动读写操作

 

SharedAddin以及VSTO开发方式在企业级应用中使用的比较广泛,下面是一些例子:

  1. SQL Server Data Mining for Excel Addin

Excel DataMining

  1. SQL Server PowerPivot for Excel Addin

PowerPivort

  1. Visual Studio Team Foundation for Excel Addin

TFS Addin

  1. Oracle BI for Excel Addin

Oracle BI Add-In for Excel

  1. Acrobat Reader for Excel Addin

Acrobat

  1. 还有一些国内的财经软件Excel插件,比如万得资讯的Excel插件

WindExcelAddin

 

4 Office App

随着Office 2013 和Office 365 的推出,Office更加注重网络化功能,因此引入了新的编程方式,那就是Apps for Office。在VS2012 中,您可以使用内置提供的Apps for Office模 板创建基于Web的Office应用程序。和传统的安装插件(VSTO)及 运行宏(VBA)不同,在新版的Office中,用户可以到微软的Office App Store中去下载,安装应用程序,这些应用程序在独自安全的沙箱环境中运行。Office Apps使用熟悉的Web技术开发如JavaScript,使得非常容易使用Mashup技术来聚合各种各样的资源。

下图展示的是使用在Excel中使用在线字典App来检索信息和Bing App来绘制和渲染专题图的效果。

Office App

还有一个优点是,Office App能够同时在本地的Office应用程序和Office在线应用程序中使用,比如本地的Excel 2013 和Excel Web App能够使用同一套JavaScript API来调用。更重要的是,因为是基于Web的,所以开发者可以使用自己熟悉的Web开发技术如JavaScript,CSS,WebService等来 开发Office App。Office App能够更方便将应用程序发布到Office App Store共享和下载,还可以通过付费赚取收益。另外对于企业及应用,可以使用企业App类别来限制只有企业内部员工才能访问下载,这些便利对于以前的 Office开发方式都是不具备的。

5 XLL

XLL是Excel的一种外接应用程序,他使用C和C++开发,程序通过调用Excel暴漏的C接口来实现扩展功能。这种方式开发的应用程序效率高,但是 难度大,对开发者自身的要求较高。著名的开源项目Excel-DNA就是使用XLL技术开发的,Excel-DNA能够帮助.NET 开发人员来极大地简化RTD函数,同步、异步UDF函数的编写和开发。 开源软件finansu 是一款可以从Bloomberg.com, Google Finance and Yahoo! Finance财经中获取股票行情数据的软件,其中大量使用了Excel-NDA。

XLL Add-Ins

finansu

上图动画简要概述了该插件功能。里面使用到了Excel-NDA中的RTD函数,异步UDF函数等功能。

XLL式的插件开发,使得系统插件不需要依赖注册表项,只需要像VBA或者VAB宏文件XLA应用那样直接在启动时加载即可使用。后面我会专门讲解Excel-DNA函数的使用。

6 OpenXML SDK 及其它

另外在有些情况下,如果再用户没有安装Excel应用程序,或者在服务器端需要动态生成Excel文件的时候。我们可能需要直接读取或者生成Excel文 件,这种情况下,即使在机器上装了Excel开发环境,调研Com组件生成Excel文件可能会导致效率十分低下。由于在Office 2007版本推出了新的.xlsx这种标准的格式,在这种情况下,我们可以直接使用一些能够操作和生成Excel文件的SDK来直接进行操作。 OpenXML SDK是微软官方推荐的操作Excel 07及以上文件格式的SDK,目前版本是2.0版本。如果要对Excel文件进行各种定制化开发的话,建议使用OpenXML。另外从Java开源项目 POI上移植过来的NPOI项目也可以直接读写Excel文件,这些效率都比直接调用Office的Com组件生成文档要快的多。

二 Office开发技术方案的选择

如前所述,要开发Excel应用程序,有很多方案可以选择。在作出选择之前,根据个人经验,有以下几方面需要考虑:

1 应用程序的类型及功能

根据Excel插件开发的功能需求,对于以些较简单的应用,比如一些Excel模板等,可以直接采用VBA宏进行定制,如果具有.NET 基础,可以采用VSTO Document-Level的方式来开发模板;对于一些较大型的或者比较复杂的一些应用,或者考虑到效率,编写VAB可能难以实现某些功能这时可以考虑 采用SharedAddin或者VSTO Addin的方式来进行开发,他能够直接利用.NET平台上的各种语言及类库,并且可以使用Visual Studio这种强大的工具来开发和进行调试;如果对应用程序的跨平台,或者移动性要求较高,或者是需要在已有的Web应用程序上建立Office应用程 序,则可以考虑使用Office App的方式来进行开发;如果应用程序对效率和要求较高,并且具有扎实的C或者C++基础,可以采取XLL的方式对Excel进行扩展;对于一些需要批量 生产Excel文件的应用环境,比如在服务器上生产Excel文件,导出数据到Excel,对Excel文件进行合并分割等操作,采用OpenXML SDK、NOPI等第三方具有直接读写Excel文件的SDK来进行开发能够获取更高的效率,另外采用第三方SDK可以使得部署的目标机器不需要安装 Office的可编程环境。

2 程序兼容Office的版本问题

第二个比较重要的考虑因素是应用程序的兼容版本问题。这个问题就像是开发BS应用程序需要考虑应用程序的类型比如是IE还是Chrome以及版本,比如需 要处理IE6 下各种头疼的问题等等。开发Excel应用程序也需要注意这一点,虽然最新的Excel2013已经推出,但是仍有大部分的客户机器可能使用的是2003 的系统。这种情况下,如果使用VSTO Application Addin的方式可能不能兼容2003的系统,并且一些特殊的UI界面如Ribbon菜单,Customer Task Panel在03版本上不兼容。这种情况下,有时候可能需要采用一些比较通用的技术如VBA,XLL,SharedAddin技术来进行处理,另外对于一 些07及以上版本中特有的UI界面和功能,使用SharedAddin开发,并且如果想利用这些功能,可能需要进行一些手动的编码和判断。另外,如果采用 VSTO编程,还有一个重要的考虑因素是.NET的版本问题,Excel插件通常是和其他产品绑定在一起发布或者销售的,有时候可能限定平台在.NET 2.0 上,那么选择VSTO的版本,及开发工具的时候可能就需要注意了。如果确定目标用户使用的Office版本为比较新的版本,如2007或者以上,建议还是 使用VSTO较高的版本进行开发,这样可以极大地简化开发的难度,提高应用程序的性能。如果客户使用的是最新版的Office,采用Office App的开发方式也是一种比较好的选择。

三 Excel开发的未来

微软推出的这么多种Excel开发方式是为了满足不同层次用户对Excel进行定制化而推出的解决方案。在可见的未来,微软会对以上的开发方式提供长久的 支持,只要满足当前应用程序的需求,目前来看对各种技术的投资仍旧是值得的。其次,最新引入的Apps for Office基于Web技术的开发方式在发布共享,安装部署,在线协作,定制化云服务,网络聚合,本地和网络应用程序兼容方面都具有一定的优势,如果想扩 展您的程序让更多的人使用,可以尝试一下Apps for Office;最后在Cindy Meister大神认为随着微软推出的新的Office Open XML 文件格式,使用OpenXML SDK可以直接操作Excel文件来创建更多的定制化功能。

四 Excel开发的资源

本文及后面的文章主要介绍ShardAddin和VSTO开发,所以下面列出我所看过的觉得有用的一些资源:

1.MSDN 论坛相应的模块:

2.博客

3.书籍

五 结语

本文主要介绍了Excel开发的各种方式及其特点,并在此基础上介绍了开发Excel插件技术选择时所需要考虑的因素,最后给出了一些相关的开发资源。后 面的文章将会重点介绍SharedAddin和VSTO开发方式,这种目前企业级的开发方式能够开发出功能强大的Excel插件。后面会逐一讲解 Excel中的菜单系统,Excel CTP用户自定义面板,Excel对象模型,同步和异步自定义函数,RTD自动刷新函数,Excel安装与部署,Excel插件开发性能调优,Excel 各版本兼容的Hack等内容,希望对大家认识和了解Excel开发有所帮助。

[转载]构建RESTful风格的WCF服务 - 逐鹿天下 - 博客园

mikel阅读(994)

[转载]构建RESTful风格的WCF服务 – 逐鹿天下 – 博客园.

RESTful Wcf是一种基于Http协议的服务架构风格。 相较 WCF、WebService 使用 SOAP、WSDL、WS-* 而言,几乎所有的语言和网络平台都支持 HTTP 请求。

RESTful的几点好处:

1、简单的数据通讯方式,基于HTTP协议。避免了使用复杂的数据通讯方式。

2、避免了复杂的客户端代理。

3、直接通过URI资源定向即可把服务暴露给调用者。

下面使用一个简单的demo项目来看看啥是RESTful Wcf。

1、项目结构【VS2010+.net 4.0】:

2、接口定义:定义了2个方法,分别代表GET、POST典型请求方式。

复制代码
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.ServiceModel;
 6 using System.ServiceModel.Web;
 7 using MyWcfService.Model;
 8 namespace MyWcfService
 9 {
10     [ServiceContract(Namespace = ServiceEnvironment.ServiceNamespace, Name = "user")]
11     public interface IUserService
12     {
13         /// <summary>
14         /// 根据code获取对象(GET请求处理)
15         /// </summary>
16         /// <param name="code"></param>
17         /// <returns></returns>
18         [OperationContract]
19         [WebGet(UriTemplate = "search/{code}", ResponseFormat = ServiceEnvironment.WebResponseFormat, RequestFormat = ServiceEnvironment.WebRequestFormat, BodyStyle = ServiceEnvironment.WebBodyStyle)]
20         UserInfo GetUserInfoSingle(string code);
21 
22         /// <summary>
23         /// 注册新的用户(POST请求处理)
24         /// </summary>
25         /// <param name="user">注册用户信息</param>
26         /// <returns>注册成功返回注册用户基本信息</returns>
27         [OperationContract]
28         [WebInvoke(Method = "POST", UriTemplate = "register", ResponseFormat = ServiceEnvironment.WebResponseFormat, RequestFormat = ServiceEnvironment.WebRequestFormat, BodyStyle = ServiceEnvironment.WebBodyStyle)]
29         UserInfo Register(UserInfo user);
30     }
31 }
复制代码

3、服务实现类WcfUserService:

复制代码
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Runtime.Serialization;
 5 using System.ServiceModel;
 6 using System.ServiceModel.Web;
 7 using System.Text;
 8 using MyWcfService.Model;
 9 using System.ServiceModel.Activation;
10 
11 namespace MyWcfService
12 {
13     [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
14     public class WcfUserService : IUserService
15     {
18         public UserInfo GetUserInfoSingle(string code)
19         {
20             // var request= WebOperationContext.Current.IncomingRequest;
         //测试数据
21             IList<UserInfo> list = new List<UserInfo>()
22             {
23                 new UserInfo(){ Id=1, Code="000001", Name="乔峰", Description="乔大爷啊"},
24                 new UserInfo(){ Id=2, Code="600000", Name="段誉", Description="你爹真是风流倜傥啊"}
25                 new UserInfo(){ Id=3, Code="000002", Name="慕容复", Description="妹子被楼上的抢咯,太失败了"},
26                 new UserInfo(){ Id=4, Code="000008", Name="庄聚贤", Description="无所事事的帅哥庄聚贤"}
27             };
28             return list.Where(e => e.Code == code).FirstOrDefault();
29         }

32         public UserInfo Register(UserInfo user)
33         {
34             if (user == null)
35                 return null;
36             user.Description = "POST搞定了!";
37             return user;
38         }
40     }
41 }
复制代码

4、定义web资源请求和响应格式:

复制代码
 1 /// <summary>
 2         /// web请求格式
 3         /// </summary>
 4         public const WebMessageFormat WebRequestFormat = WebMessageFormat.Xml;
 5 
 6         /// <summary>
 7         /// web相应格式
 8         /// </summary>
 9         public const WebMessageFormat WebResponseFormat = WebMessageFormat.Xml;
10 
11 
12         /// <summary>
13         /// 请求内容封装方式
14         /// </summary>
15         public const WebMessageBodyStyle WebBodyStyle = WebMessageBodyStyle.Bare;
复制代码

5、Global全局资源文件,注册服务的路由:

复制代码
 1         protected void Application_Start(object sender, EventArgs e)
 2         {
 3             RegisterRoutes();
 4         }
 5 
 6         private static void RegisterRoutes()
 7         {
 8             RouteTable.Routes.Add(new ServiceRoute("user", new WebServiceHostFactory(), GetServiceType("WcfUserService")));
 9         }
10 
11         private static Type GetServiceType(string typeName)
12         {
13             string typeFullName = String.Format("MyWcfService.{0},MyWcfService", typeName);
14             return Type.GetType(typeFullName);
15         }
复制代码

6、wcf配置文件:

复制代码
 1  <system.serviceModel>
 2     <bindings>
 3       <netTcpBinding>
 4         <binding name="defaultNetTcpBinding" closeTimeout="00:01:00"
 5             openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
 6             transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
 7             hostNameComparisonMode="StrongWildcard" listenBacklog="10"
 8             maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="100"
 9             maxReceivedMessageSize="2147483647">
10           <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
11               maxBytesPerRead="4096" maxNameTableCharCount="16384" />
12           <reliableSession ordered="true" inactivityTimeout="00:10:00"
13               enabled="false" />
14           <security mode="None">
15             <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
16             <message clientCredentialType="Windows" />
17           </security>
18         </binding>
19       </netTcpBinding>
20     </bindings>
21     <behaviors>
22       <serviceBehaviors>
23 
24         <behavior name="defaultResultBehavior">
25           <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
26           <serviceMetadata httpGetEnabled="true"/>
27           <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
28           <serviceDebug includeExceptionDetailInFaults="true"/>
29           <dataContractSerializer maxItemsInObjectGraph="6553500"/>
30         </behavior>
31       </serviceBehaviors>
32       <endpointBehaviors>
33         <behavior name="defaultRestEndpointBehavior">
34           <webHttp helpEnabled="true" automaticFormatSelectionEnabled="true" />
35           <dataContractSerializer maxItemsInObjectGraph="6553500"/>
36         </behavior>
37         <behavior>
38           <dataContractSerializer maxItemsInObjectGraph="6553500"/>
39         </behavior>
40       </endpointBehaviors>
41     </behaviors>
42     <services>
43       <service name="MyWcfService.WcfUserService" behaviorConfiguration="defaultResultBehavior">
44         <endpoint contract="MyWcfService.IUserService" binding="webHttpBinding" behaviorConfiguration="defaultRestEndpointBehavior" />
45       </service>
46       
47     </services>
48     <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
49   </system.serviceModel>
复制代码

文件代码都准备的差不多了,运行服务看下效果:

调用GET方法,返回xml数据:

ok,一个RestFul WCF就搭建完毕。

下一篇文章还是基于这个demo,如何使用dynamic解析Http RestFul xml格式响应数据,并展现在客户端。

[转载]高级别问题:如何在ASP.NET大型应用系统的模块化开发实现多版本程序集并存支持 - 道法自然 - 博客园

mikel阅读(879)

[转载]高级别问题:如何在ASP.NET大型应用系统的模块化开发实现多版本程序集并存支持 – 道法自然 – 博客园.

这是我最近碰到的一个问题,有一家企业.NET程序员有80多人,产品线很多也很复杂。 对于这样的产品,他们采用了模块化开发来实现复用与协作。不过,这样做需要解决一个问题,就是在一个产品中,不同模块由不同Team来开发,他们可能会引 用同一个程序集的不同版本。这时候,你该怎么来解决呢?

 

我先亮出基于iOpenWorks插件框架(你可以访问http://www.iopenworks.com/Products/SDKDownload来下载这个插件框架)解决方法,然后描述这个问题的上下文,最后可由读者们来提提你们的解决方案。

 

在部门管理模块中,我们使用了一个程序集的1.0.0.1版本,分别在代码和ASP.NET页面中引用了该程序集,如下所示。传统在ASP.NET 页面中使用程序集的方法是:(1)使用Import标签来声明引用的类型空间,接着使用其类型;(2)使用指定命名空间的类型来调用。需要注意的是,为了 降低开发复杂度,模块使用多版本程序集的方法和以前的方法相同,从而避免模块化引起的侵入性负效应。在下图中,你可以发现支持多版本的模块化开发方法和原 有方式一模一样。

image

在用户管理模块中,我们使用了一个程序集的1.0.0.0版本,也分别在代码和ASP.NET页面中引用了该程序集,如下所示。

image

这两个模块由两个团队来分别开发,由于管理和进度原因,他们使用了同一个程序集的不同版本,此时,基于OSGi.NET的实现方案结果如下。在用户 管理里面,显示结果为1.0.0.0的结果,即打印出“ROOT”;在部门管理里面,显示结果为1.0.0.1的结果,即打印“ROOT- v1.0.0.1”。

image

 

iOpenWorks插件框架针对多版本程序集的支持方案的核心是实现正确的类加载,其实现核心为2点,如下所示:

(1)通过对CLR扩展,支持多版本程序集的类加载;

(2)扩展ASP.NET页面编译方法,为每一个ASP.NET页面编译设置正确的程序集版本。

 

这个示例的源码如下:点击下载源码

 

除了iOpenWorks插件框架的解决方法,针对这个问题,各位看官有其它办法来解决吗?

Creative Commons License

有任何技术问题,可以加入iOpenWorks插件仓库平台QQ交流群: 121369588。

本文基于Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名道法自然(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。