F# - Open System.Data.SQLite

System.Data.SQLite.dll可以从sqlite.phxsoftware.com得到. 冷门的语言+冷门的应用. 不多解释了, 直接上代码:

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#light
open System
open System.Data
open System.IO
#r "System.Data.SQLite.DLL"
open System.Data.SQLite
// 输出调试结果到命名行
let debug x =
x |> print_any
Console.WriteLine()
let space = [|for i in 1 .. 50 -> "*"|] |> string.Concat
// 数据库文件名
let dbFileName = "HelloSQLite.sqlite"
// 连接字符串
let connString =
let builder = SQLiteConnectionStringBuilder()
builder.DataSource <- dbFileName
builder.ConnectionStringspace |> debug
"连接字符串: " + connString |> debug
// 创建数据库文件
space |> debug
"创建数据库..." |> debug
try
dbFileName |> File.Delete
SQLiteConnection.CreateFile dbFileNamewith e ->
e |> debug
let test _ =
use conn = new SQLiteConnection(connString)
use cmd = conn.CreateCommand()
conn.Open()
// 开始计时
let watch = new System.Diagnostics.Stopwatch()
watch.Start()
space |> debug
"创建表..." |> debug
try
(* SQLite 官方文档提及的数据类型只有5种: NULL INTEGER NUMERIC TEXT BLOB 你可能觉得太少了, 事实上 SQLite 是弱类型, 建表时定义的数据类型只是个标识, 对数据列的类型并没有实质性的作用. 你也可以把 TEXT 类型定义成更复杂的 NVARCHAR(50) 之类的, 这只是为了未来数据迁移的方便. *)
cmd.CommandText <- "CREATE TABLE [Test] ( " +
"[Int32] INTEGER NOT NULL, " +
"[String] TEXT NOT NULL)"
cmd.ExecuteNonQuery() |> ignore
with e ->
conn.Close()
e |> debug
watch.Elapsed |> debug
watch.Reset()
watch.Start()
space |> debug
"乱入数据十万行..." |> debug
use trans = conn.BeginTransaction()
cmd.Transaction <- trans
try
// 注意: Int32这个列名有些误导, 封装的作者提及 INTEGER 对应 ADO.net 2.0 的 Int64 类型
cmd.CommandText <- "INSERT INTO [Test](Int32, String) " +
"VALUES(?, ?)"
// 下面这种生成参数的方式 在参数较多时会有方便 但不能用seq
[for i in 0 .. 1 -> cmd.CreateParameter()]
|> List.to_array
|> cmd.Parameters.AddRange
|> ignore
// 参数化插入 这是官方推荐的方式 性能最好
for i in 0 .. 99999 do
let vl = [box i; box ((i * 1000).ToString())]
for j = 0 to (cmd.Parameters.Count - 1) do
cmd.Parameters.[j].Value <- List.nth vl j
cmd.ExecuteNonQuery() |> ignore
trans.Commit()
with e ->
trans.Rollback()
conn.Close()
e |> debug
watch.Elapsed |> debug
watch.Reset()
watch.Start()
space |> debug
"查询前3行..." |> debug
try
cmd.CommandText <- "SELECT * FROM [Test] " +
"WHERE [Int32]<3"
use reader = cmd.ExecuteReader()
while reader.Read() do
reader.GetInt32 0 |> debug
reader.GetString 1 |> debug
with e ->
e |> debug
watch.Elapsed |> debug
watch.Stop()
conn.Close()
test()
Console.ReadKey()

Blizzard冰封之谜

暴雪官方站出现了一个神秘的Splash页面, 似乎有什么东西要破冰而出?

第一天:

第二天:

第三天:

第四天:

第五天:

第六天: (5andahalf 竟然是5.5 T_T):

除此之外, 在首页源代码中唯一的.css文件里, 可以看到被注释掉的图片:

http://us.media.blizzard.com/232309/master.css

拼图已经完整:

好眼生的说! 他/她/它是?

DiabloIII 终于见到了真容:

取代ice图片的过场Flash动画

暴雪官方的暗黑3站点: http://www.blizzard.com/diablo3

人物设定 (目前仅有野蛮人和术士): http://www.blizzard.com/diablo3/characters/

媒体资源页面: http://www.blizzard.com/diablo3/media

目前公布了三段视频, 官方页面还没有搞好, 下载视频需要确认生日是否够18岁, 但那个FLASH中的日期在IE和FF下都无法正常选择. 所以附上直接下载的地址:

Diablo3 cinematic trailer

Diablo3 gameplay trailer

Diablo3 artwork trailer

Silverlight 2 Beta2 + WCF = 404 Error ?

大致情形是这样的:

  • Silverlight 2 beta2 (目前最新的支持 VS2008 中文版的开发包)
  • WCF (采用 SL2b2 安装后新增的那个模板创建的)
  • LINQ to SQL (对应 SQL 服务器中的四个表)

使用 DataGrid 控件来显示和编辑 SQL 中的 Component 表, 强大的LINQ帮我创建了一个对应的 Component 类, 查询和显示的过程很顺利.

可是到了更新数据这一步, 却碰上了莫名其妙的 404 错误… 少量可以, 大量数据就会出错.

The remote server returned an unexpected response: (404) Not Found.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[OperationContract]
public List<Component> QueryComponentList(Guid TowerID)
{

using (var db = new LINQDataContext())
{
var linq =
from l in db.Component
where l.TowerID.Equals(TowerID)
orderby l.Section, l.Number
select l;
return linq.ToList();
}
}

[OperationContract]
public void UpdateComponentList(Guid tid, List<Component> source)
{

using (var db = new LINQDataContext())
{
...
}
}

在官方论坛上我看到了N种解释, 总结如下:

跨域安全问题, 也就是传说中的 crossdomain.xml 和 clientaccesspolicy.xml 两个文件. 试试, 虽然我知道不会奏效的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- crossdomain.xml -->
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
<!-- clientaccesspolicy.xml -->
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

Silverlight 项目中的 ServiceReferences.ClientConfig 文件, 增大 maxBufferSize 和 maxReceivedMessageSize. 我加到了 2147483647, 也就是 2G, 结果不行.

1
<binding name="BasicHttpBinding_WCF" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>

网站中的 web.config 文件, 增大若干个 max 开头的属性. 我估计有几项是客户端根本无法识别的 设置了也没用…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_WCF" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxDepth="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WCFBehavior" name="WCF">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_WCF" contract="WCF" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>

在 web.config 文件中的 system.web/httpRuntime 节点下, 设置 POST 允许的最大长度, 以kb为单位, 那就是 int.MaxValue/1024=2097151. 早就知道问题不在这…

1
<httpRuntime maxRequestLength="2097151"/>

web.config 中关于 WCF 还有个秘密, 那就是 system.serviceModel/behaviors/serviceBehaviors/behavior/dataContractSerializer. 天啊, 连这个都有人挖出来啦! 兴奋了几秒钟, 发现还是没搞定!

1
2
3
4
5
6
7
8
9
<behaviors>
<serviceBehaviors>
<behavior name="WCFBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<dataContractSerializer maxItemsInObjectGraph="2147483647" ignoreExtensionDataObject="true" />
</behavior>
</serviceBehaviors>
</behaviors>

仔细回忆到底是哪里出了问题, 我发现当数据少于 176 行时是没有问题的, 只要一超过这个数量, 就会弹出异常, 而且感觉上是在异步传递数据之后立即发生的, 比能够上传成功的 176 行数据响应的还快许多, 更奇怪的是虽然 VS2008 跳出异常, 接收到了 404 错误, 但此时任务管理器的 WebDev.WebServer.EXE 和 sqlserver.exe 都正忙着, 查看 SQL 发现数据也是成功写入了…

那这 404 是哪里来的鬼东西? 无意中直接打开 IE 不经过调试, 结果我也没接收到 404 错误, 真的无奈了, 最后决定死马当活马医. 把上传数据那个函数从 void 类型改成 bool 类型, 让它具备一个布尔型的返回结果, 以确认上传是否成功(之前一直感觉这是多余的).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[OperationContract]
public bool UpdateComponentList(Guid tid, List<Component> source)
{

try
{
using (var db = new LINQDataContext())
{
...
}
return true;
}
catch (Exception)
{
return false;
}
}

古怪的问题就这样华丽的消失了… 别问我为什么, 我也不知道!

Silverlight 2 Beta2 把我们都涮了

之前曾经写过一篇 矫情的 Silverlight 开发工具包

不过之后我又发现相比刚刚推出的 beta2 版来说, 之前的 beta1 版算是比较的谦和了. 为什么这样说呢? 且看下去:

当我在尝试安装 Silverlight 2 beta2 开发包的时候, 相同的错误对话框再一次出现了, 我确定这次一定与前次不同, 因为我已经有了教训, 把与 Silverlight 相关的所有成员全部驱逐出境了, 我真的不得不佩服这个经典的错误对话框, 因为它帮你仔细的列举了所有出错的可能性, 却并不指明到底是哪条错误导致安装失败的.

为了一探究竟, 我将安装包解压了, 发现这次包含的 VS2008 补丁与前次不同, 名称是 VS90-KB950630.msp, 直接双击安装, 提示如下:

Windows Installer 服务不能安装此升级修补程序, 因为找不到要升级的程序, 或者升级修补程序可能更新的是不同版本的程序. 请验证要升级的程序存在, 并且您的升级修补程序正确.

已经可以确认安装错误的原因就是它了, 但为什么呢? 我到微软的网站上看了一下, 有两种语言可选, 我决定将日文安装包下载下来比对一下, 竟然发现在日文包内的 VS2008 补丁名称是 VS90-KB950631.msp

一切都明白了, 这下你知道为什么中文版的 VS2008 在安装 Silverlight 2 beta2 时全军覆没了吧!

使用 VS2008 中文版的朋友, 可以暂时放弃了, 别再为此事浪费心情了. 微软正在做本地化工作, 在还没有完成的情况下就抛出了这个 beta2 的安装包, 把我们这些人都涮了…

F# resxc.exe BUG

我在研究如何把资源嵌入 F# 程序时, 从 F# 的示例中找到了答案 —- Samples101

示例的编译参数主要部分如下:

%FSC% --no-warn 62 -o samples101.exe SampleForm.resx sample.fs beginnersInLightSyntax.fs sampleform.fs program.fs

这其实是把 .resx 资源当作工程的一部分直接编译到 .exe 当中.

当我使用 FSharp-1.9.4.17 对其进行编译的时候, 我发现生成的 samples101.exe 文件尺寸有些不大对劲, 竟然有 323KB. 尝试使用 Reflector for .NET 打开生成的可执行文件, 我惊奇的发现, 文件内竟然嵌入了七个相同的资源.

查阅一些资料后明白, 原来在将 .resx 资源添加到工程中, 编译时会调用 resxc.exe 将 .resx 转化成 .resources 资源, 编译完成后又删除了中间过程产生的 .resources. 于是我试着使用 resxc.exe 手动生成 .resources, 发现生成的资源文件竟然比原有文件大了数倍. 看来问题就出现在 resxc.exe 身上了.

接下来的一切也证明了这一点, 使用 Reflector for .NET 打开 .resx 文件, 再另存为 .resources, 文件按照预期的尺寸生成了, 比原有文件稍小, 毕竟是相同的内容, 二进制的 .resources 文件当然要比十进制 XML 格式的 .resx 文件小一点才对.

把直接嵌入的方式改为使用参数嵌入 --resource SampleForm.resources, 文件尺寸也降至 119KB.

我考虑到了正在使用的 Win2k8 系统的特殊性, 又在一台只有 F# 安装包和 .NET 的 WinXP 系统的笔记本上试了一下, 资源还是被嵌入了七次. 或许这真的是一个 七次资源 BUG (7 Times Resources BUG)

矫情的 Silverlight 开发工具包

silverlight_chainer.exe 也就是那个 Silverlight 2 SDK 的全套开发工具包, 安装的时候报错.

An Error Has Occurred:

Silverlight Tools cannot be installed because one or more of the following conditions is true:

  1. Visual Studio 2008 RTM is not installed.
  2. The Web Authoring feature of Visual Studio is not installed.
  3. A previous version of the Silverlight Runtime is installed.
  4. A previous version of the Silverlight SDK is installed.
  5. The Visual Studio Update KB949325 is installed.
  6. A previous version of Silverlight Tools is installed.

To continue, please install or uninstall the appropriate products and run this installer again.


发生错误:

Silverlight 工具因为下面问题中的一个或多个而无法安装:

  1. 未安装 Visual Studio 2008 RTM.
  2. 未安装 Visual Studio 的 WEB 创作功能.
  3. 已安装上一版本的 Silverlight 运行时.
  4. 已安装上一版本的 Silverlight SDK.
  5. 已安装 Visual Studio 更新 KB949325
  6. 已安装上一版本的 Silverlight 工具

要继续, 请安装或卸载适当的产品后再运行安装包.


逐一排除!

  1. 不可能!
  2. 开玩笑!
  3. 装过, 刚刚卸载了!
  4. 同上!
  5. 这个…我也不知道!
  6. 什么工具? 上一版有工具么?

看来原因就在这个 KB949325 上面, 看了下已安装的更新, 还真有这个家伙, 全称很长:

Update for Microsoft Visual Studio 2008 专业版 - 简体中文 (KB949325)

卸载过程让人大跌眼镜, 竟然启动 VS2008 的维护模式, 持续1分钟之久…

我终于明白上次 Silverlight 2 工具包在安装进度条到了100%之后, 我出去抽根烟又和同事聊了会儿天, 回来发现竟然还没有装好的原因了.

F# 编译器参数说明 (Fsc --Full-Help)

fsc --full-help

MSR F# Compiler, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.9.4.17, compiling for .NET Framework Version v2.0.50727
Usage: fsc [imported.dll … ] [file1.ml [file2.ml …] ]

基本选项:

  • -I : 指定包含的路径目录.
  • -r : 引用 F# 或 .NET 程序集.
  • -R : 引用 F# 或 .NET 程序集并复制到本地.
  • -o : 命名输出文件.
  • -a: 生成 DLL.
  • -g: 生成调试文件. 如果未指定 -O 时禁用优化.
  • —define : 定义给定的条件编译符号.
  • -i: 输出程序集的推导接口.
  • -doc : 将程序集的 XML 文档写入指定文件.
  • -Ooff: 禁用所有的优化, 包括 JIT.
  • -O0: 允许 JIT 优化.
  • -O1: 允许 JIT 和本地优化.
  • -O: 类似 -O2 (未使用 -g 时的默认值)
  • -O2: 类似 -O1, 允许跨模块优化.
  • -O3: 类似 -O2, 增加内置和对 lambda 表达式的优化.
  • —no-mllib:
    • 不引用 FSharp.Compatibility.dll 或
      open Microsoft.FSharp.Compatibility.OCaml.Pervasives,
      当希望避开对该模块的依赖时很有用.
  • —all-warnings: 输出全部警告.
  • —no-warnings: 不输出警告.
  • —warn : 报告指定的警告.
  • —no-warn : 不报告指定的警告.
  • —all-warnings-as-errors: 将全部警告视为错误.
  • —warn-as-error : 将指定的警告视为错误.
  • —gnu-style-errors: 输出 GNU 风格的带行号的错误.
  • —namespace :
    • 定义默认的根命名空间, 包括后来定义的 F# 子模块.
  • —open :
    • 打开指定模块作为每个源文件的初始定义.
  • —fullpaths: 编译器生成完整的路径描述.
  • —clr-root :
    • 用于取代编译器寻找 mscorlib.dll 和构造组件的路径. 通常用于
      —cli-version, 编译 Silverlight 或 .NET Compact Framework
  • —ml-compatibility: 忽略 OCaml 兼容性警告.
  • —ml-keywords:
    • 将 F# 中不属于 OCaml 的关键字视为标识符.
  • —copy-local :
    • 定位搜索路径中的指定文件, 复制到本地(例如 PDB).
  • —compiling-fslib:
  • —compiling-mllib:
  • —generate-interface-file :
    • 输出程序集的推导接口到文件.
  • —target-exe: 生成命令行可执行文件.
  • —target-winexe: 生成不带 stdin/stdout/stderr 的可执行文件.
  • —target-dll: 生成 DLL
  • —target-module: 生成模块, 用于添加到另一个程序集.
  • —auto-resolve: 自动引用 DLLs, 根据名称匹配需要的 F# 模块或命名空间. 实验性.
  • -c: 编译成模块 (—target-module) 并且自动解析 (—auto-resolve). 实验性.
  • —standalone:
    • 静态链接 F# 库和所有涉及依赖 F# 库的 DLLs 到生成的程序集. 禁止生成 F#
      接口并优化资源, 同时重命名所有 Microsoft.FSharp 开头的类型, 把它们
      置于目标程序集的内部. 静态链接的程序集中类型名不能重复, 也不能使用代码
      映射程序集中的类型, 并且也不能使用代码暴露 F# 库类型作为 API.
  • —static-link :
    • 静态链接给定的程序集和所有涉及到的 DLLs.
      注意: 使用程序集名称 例如 mylib, 而不是 DLL 名称 例如 mylib.dll.
  • —keyfile :
    • 用给定的 key 文件注册程序集, 就像用 .NET Framework SDK 中的 \’sn.exe\’
      工具一样. 它为程序集生成强名称. 这仅在生成在不同目录程序之间共享的
      同一程序集时有用, 例如安装到 GAC (Global Assembly Cache).
  • —public-keyfile :
    • 使用给定的公开 key 文件延迟注册. 程序集随后可以使用 .NET Framework SDK
      中的 \’sn.exe\’ 完成注册.
  • —retargetable : 指定程序集可以引用 retargetable 形式. 用于创建独立于
    • 引用 DLLs 发行者的二进制文件.
  • —win32res : 指定 Win32 资源文件 (.res)
  • —platform : 限定代码可以在哪种平台上运行:
    • x86
    • anycpu
    • 默认是 anycpu. 其他平台限制规则尚不可用 如 x64 和 Itanium.
  • —resource : 嵌入指定的托管资源 (.resource).
    • 可以使用 resgen.exe 或 resxc.exe 从 .resx 文件生成 .resource 文件.
  • —link-resource :
    • 链接指定的托管资源文件 (.resource).
    • 格式类似于 [,[,public|private]].
    • 可以使用 resgen.exe 从 .resx 文件生成 .resource 文件.
  • —base-address : 用于创建库的基础地址.
  • —version-file :
  • —version :
    • 为产生的 .NET 程序集产生版本号 (例如 1.2.0.1).
  • —cli-version :
    • 为指定的 CLI 版本产生代码, 不理会在编译时所安装的运行时 CLI.
    • 当前版本的 F# 可用值: 1.0, 1.1, 2.0
    • 创建标签例如 v2.0.x86chk
    • 你还需要把正确的 Framework 目录添加到包含路径中
      —clr-root \WINDOWS\Microsoft.NET\Framework\v1.1.4322
    • 当然还需要对你的二进制文件运行适当版本的检验, 例如
      C:\Program Files\Microsoft Visual Studio .NET 2003
      \SDK\v1.1\Bin\PEVerify.exe
    • 以确保你和你导入的库没有使用指定 .NET Framework 版本之外的特性.
  • —clr-mscorlib :
    • 指定目标 CLR 上的 mscorlib
  • —debug-file :
    • 命名 debug 输出文件.
  • —generate-debug-file:
  • —no-debug-file:
    • 控制是否产生 debug 信息. 与 -g 不同, 它默认不关闭优化.
  • —generate-html:
    • 生成 HTML 文档.
  • —html-output-directory :
    • 输出 HTML 的目录.
  • —html-css :
    • 设置 HTML 文档的 CSS (Cascading Style Sheet).
  • —html-namespace-file :
    • 设置主要的 namespaces.html 文件名称, 假定在输出目录.
  • —html-namespace-file-append:
    • 当生成 HTML 文档时附加到主要的命名空间文件.
  • —no-optimization-data:
    • 仅包括必要的实现内部结构的优化信息. 抑制内部跨模块可以改善二进制兼容性.
  • —generate-optimization-data-file:
    • 将优化信息放入一个 .optdata 文件
  • —no-interface-data:
    • 不将资源添加到产生的程序集当中, 包括用于其他 F# 程序集的接口数据. 程序集
      只能被 .NET 程序集访问.
  • —quotation-data:
    • 这一标志已过时. 代之使用 \’ReflectedDefinition\’ 属性.
  • —generate-config-file:
    • 生成配置文件确保 .exe 运行在 —cli-version 指定的版本上. 文件包含
      \’supportedRuntime\’ XML 元素.
  • —jit-optimize:
  • —no-jit-optimize:
  • —local-optimize:
  • —no-local-optimize:
  • —cross-optimize:
  • —no-cross-optimize:
    • 细微深入的控制 JIT 本地和跨模块.
  • —fast-sublanguage-only:
    • 限制 F# 语言中很难有效编译的细微规则结构, 为编译器争得更多的优化机会.
      配合下面所有的 —no-ABC 标志. 能显著改善性能.
  • —no-inner-polymorphism:
    • 不允许内部绑定到真正的泛型.
  • —permit-inner-polymorphism:
  • —no-string-interning: 运行时不保留编译的字符串常量.
  • —statistics: 显示编译器统计.
  • —progress: 显示编译器进度.
  • —no-framework:
    • 默认不引用 .NET Framework assemblies 程序集.
  • —sscli:
    • 强迫编译器寻找并使用路径中的 SSCLI , 取代 Microsoft CLI.
      生成的调试信息也是 SSCLI 格式的.
  • —max-errors :
  • —generate-filter-blocks:
    • 生成过滤块以允许第一时间捕获未处理的异常.
  • —stamps:
  • —ranges:
  • —terms:
  • —termsfile:
  • —ilfiles:
  • —times:
  • —detuple :
  • —tlr :
  • —tlrlift :
  • —no-env:
  • —parse-only:
  • —typecheck-only:
  • —ast:
  • —tokenize:
  • —testInteractionParser:
  • —light:
  • —lightoff:
  • —inline-threshold :
  • —extra-optimization-loops :
  • —generics:
  • —no-generics:
    • 细微调节是否生成 .NET CLR 通用支持的代码.
  • —all-tailcalls:
  • —no-tailcalls:
    • 细微调节是否发出尾部调用注解.
  • —closures-as-virtuals:
    • 细微调节关闭实现.
  • —multi-entrypoint-closures: