摘要: 我的WCF项目系列我的WCF项目系列之一----为什么选择WCF我的WCF项目系列之二----WCF初级应用我的WCF项目系列之三----WCF配置文件和返回值我的WCF项目系列之四----WCF Oracle数据库应用我的WCF项目系列之五----WCF 面向对象开发我的WCF项目系列之六----WCF 宿主系统服务的异常退出我的WCF项目系列之七----WCF 与 Asp.net AJAX(未...阅读全文
posted @ 2010-10-25 19:55 BruceZhou 阅读(214) 评论(0) 编辑

在桌面开发中,窗体界面是最重要的开发方向之一。用户接触的都是人机交互窗体界面。在Android的开发中,窗体界面当然也是最主要的开发方向之一。而Android的窗体和桌面窗体开发有很大的区别。.Net中的C#是现在最流行的编程语言之一,现在主要介绍Android窗体和C#WinForm开发的异同。

1>C# WiForm

C#中 WinForm主要有两部分组成,1是窗体文件,2是代码文件。在窗体问中主要是存储的窗体中各个成员的默认属性,例如大小,颜色,位置等,在代码文件中当然存储的是各个成员的处理事件,方法等。

clip_image002clip_image004

clip_image006

上面的C#Winform “Form1”, 就是一个名为”Form1”的Form类的子类,类文件被分为两个部分,分别是 “Form1.cs”中的”public partial class Form1 : Form ….” 和 “Form1.Designer.cs”中的”partial class Form1 ……”,这两部分和在一块,才是一个完成的C#WinForm类。

2> Android 窗体的组成。

在Android开发中,它的窗体也是有2部分组成,不过和C#不同的是,它的窗体是完全独立的两个部分,分别是一个 Activity的子类,和xml文件(叫做LayOut布局文件)。Activity存储的就是这个窗体各个成员的处理事件,方法等,对应C#中的Form1.cs,XML文件存储的就是窗体中各个成员的布局,默认属性等,对应C#中的Form1.Design。因为是完全独立的两个部分,他们的名字当然是可以完全不相关的命名方式。

在C#中Form1就是一个窗体的组合,直接调用就可以啦。

Android中就不能这样。一个窗体的组合,必须是Activity + xml 才算完整。在Activity中有onCreate()方法,在里面指定一个xml文件,在算组成了一个完整的窗体。

clip_image008

(Activity中的onCreate方法)

clip_image010

(main布局文件的界面)

clip_image012

(main布局文件的代码)

就是把当前的Activity和”main”layout布局文件组合起来,组成了一个完整的窗体。就是在main布局文件中设定好各个成员控件的位置,属性等,在当前的Activity就可以处理他们的事件方法等。

3>主界面(或程序默认的第一个界面)

在C#开发中,Program.cs中指定了当前程序的主界面。

clip_image014

在Andorid开发中,存在一个AndroidManifest.xml文件,其中包含所有的”activity”类(相当于C#中的窗体类)的列表,其中主界面的要包含<intent-filter>成员。把要作为主界面的”activity”中加入<intent-filter>成员设置就可以啦,等同于C#的Program.cs中的”Application.Run(主界面窗体)”。如下图显示

clip_image016

3>多窗体

在C#中,如果一个程序包含多个窗体,不用什么特殊的设置,只要多创建一个From类就可以啦。

在Andorid中,也是多创建几个Activity类,不过要在AndroidManifest.xml中吧所有要显示的Activity都要列出来,否则要报错。如下图所示

clip_image018

4>跳转到另一个窗体。

在C#中要跳转的另一个窗体的代码非常简单,就是新建一个窗体,并显示就可以啦。

clip_image020

在Andorid中要稍微麻烦一些,要用到”Intent”的用法(包含的按钮单击事件到下章再介绍),如下

clip_image022

myHello.this就是当前的窗体,OtherActivity.class就表示要跳转到的窗体。

5>跳转窗体时的传参

在C#中传参可以用属性的方式传参(本教程就不多讲C#的一些写法啦,只举例其中一种),并在跳转时调用,参数的类型只要是C#支持的类型就可以。

clip_image024clip_image026

在Android中,传参方式如下:

clip_image028

上面的代码中共有3个参数 1。”textintent”, 值是”123456”,2。”one”,值是一个变量”factorOneStr”,3。”two”,值是一个变量”factorTwoStr”.

6>窗体传参时的接收

在C#中也很简单,直接调用就可以啦。代码示例如下:

clip_image030

在Andorid中,先要提取,才能调用。代码示例如下:

clip_image032

posted @ 2011-04-27 20:00 BruceZhou 阅读(258) 评论(0) 编辑
posted @ 2010-10-25 19:55 BruceZhou 阅读(214) 评论(0) 编辑

Oracle数据库调用就是一门复杂的课程啦,我这里只写在WCF中的应用。

我看到有的人在写中间层调用数据库时,单把数据库调用作为一个服务来发布,仅仅是一个远程函数,上传一个Sql+参数列表,返回一个数据集,其他所有逻辑都在客户端编写应用,这就完成一个系统的开发啦。

我觉得这种方式太狭隘啦,完全抛弃了面向对象开发的思想,又回到面向过程的开发啦。我的方式是自己写类,在类中包含属性,在服务端执行Sql结果都写到类中,再返回类,这种方式在下一篇中再介绍,这里只写数据库。

在我刚学习时用的vs2003,那是还有OracleConnection等一些.Net内置的Oracle专用类库,在VS2008时,就找不到啦,我一直用的OleDB类库。

1. 连接字符串Provider=OraOLEDB.Oracle;Password=***;Persist Security Info=true;User ID=***;Data Source=***

2. 前期是自己写的SqlHelp,后来用的EntLib,微软企业库,现在是5版本啦。

3. 调用的基本方式是

public virtual bool boExecuteSql(string strSql, string[] _parameterS, string strDBConString, DataSet dsDBRe)

{

Boolean boResult;

//

int intDiv;

intDiv = _parameterS.Length % 2;

if (intDiv > 0)

{

boResult = false;

return boResult;

};

try

{

using (SFCDBCon = new OleDbConnection(strDBConString))

{

OleDbDataAdapter empS = new OleDbDataAdapter(strSql, SFCDBCon);

int countParameter = _parameterS.Length / 2;

OleDbParameter[] myOleParameterS = new OleDbParameter[countParameter];

for (int i = 0; i < countParameter; i++)

{

if (_parameterS[i * 2 + 1].Trim().Length > 0)

{

myOleParameterS[i] = new OleDbParameter(_parameterS[i * 2], _parameterS[i * 2 + 1]);

empS.SelectCommand.Parameters.Add(myOleParameterS[i]);

}

}

SFCDBCon.Open();

empS.Fill(dsDBRe, "myTB");

}

boResult = true;

}

catch (System.Exception e)

{

string eMsg = e.Message;

boResult = false;

}

//

return boResult;

}

4. 在连接Oralce是一定要牢记,要释放Oracle连接。如果不释放,Oracle就会产生许多空链接,直到连接数满。用Using()语法就简单啦,不用手动释放。

5. 在就是参数的应用。在Delphi中数据库控件可以自动感应Sql中包含的参数,单OldDb不能自动感应,必须手工建立参数并赋值

6. 调用存储过程,因为参数是相对固定的,我采用的方法是预先从Oracle系统表中求出参数。

SELECT OBJECT_NAME,ARGUMENT_NAME,POSITION,DATA_TYPE,IN_OUT FROM USER_ARGUMENTS WHERE OBJECT_NAME = :procname ORDER BY POSITION

7. EntLib的数据访问模块,操作Oracle数据库。

8. 别忘异常处理。否则客户端报错,就不知道什么原因啦。其中又包括WCF的异常处理,和Oracle数据库操作的异常处理,分别有不同处理方式。

posted @ 2010-10-25 19:48 BruceZhou 阅读(454) 评论(0) 编辑

在学习WCF之前,就见到过另一种编程思想,叫做面向服务开发,哈哈,当时不甚了了。

前面提到,我之前一直用Delphi开发的,所以是学习的Delphi面向对象开发,记得足足有3个多月,写了22万行代码,才算是明白面向对象开发。对我以后的工作和学习打下了结实的基础。

很长时间,我都是用WCF开发服务,用Delphi开发客户端,其中数据通过WCF交互的部分没有用到面向对象开发的思想,一直到转到C#开发WinForm。

用C#开发了一些客户端期间,学习了一本书《Expret C#2005 Business Objects》,虽然最后也没有用轨道CSLA架构,可是对我的启发很大。

一直到自己摸索到的开发风格。一律用类作为WCF数据交互的参数基础。

略写如下。

1. 先对一个系统要操作的数据进行规划,类化,即相关的数据组成一个类,

2. 对主要数据集部分做成段或类,生成类的泛型列表属性

3. 当然还要完善这个类的其他成员,方法等,才能写成一个有用的类

4. 把类作为ref读写参数,或作为返回值,返回处理后的她自己

例如:

using System;

using System.Collections.Generic;

using System.Data;

using System.Text;

using myHomeLibrary;//这里写了许多基础的东西,写了一些通用的属性,成员等,算是一个基础类

namespace BufferLibrary

{

public class BufLineItem ///主要数据集部分

{

private string _line = "N/A";

private string _onLine = "N/A";

private string _onLineFeederList = "N/A";

private string _linkModel = "N/A";

private string _linkMO = "N/A";

private string _typeF = "F";

public BufLineItem ()

{

//

}

public string LineName

{

get

{

return _line;

}

set

{

if (_line == value)

return;

_line = value;

}

}

public string OnLineModel

{

get

{

return _onLineModel;

}

set

{

if (_onLineSFCModel == value)

return;

_onLineSFCModel = value;

}

}

public string OnLineFeederList

{

get

{

return _onLineFeederList;

}

set

{

if (_onLineFeederList == value)

return;

_onLineFeederList = value;

}

}

public string LinkSFCModel

{

get

{

return _linkSFCModel;

}

set

{

if (_linkSFCModel == value)

return;

_linkSFCModel = value;

}

}

public string LinkMO

{

get

{

return _linkMO;

}

set

{

if (_linkMO == value)

return;

_linkMO = value;

}

}

/// <summary>

/// TypeF的標示

/// </summary>

public string TypeF

{

get

{

return _typeF;

}

set

{

if (_typeF == value)

return;

_typeF = value;

}

}

}

public class BufLineItemS : CHome

{

//

private List<BufLineItem> _lineItemS = new List<BufLineItem>();//泛型列表属性成员

#region 构造函数,析构函数

public CBufLineItemS()

{

ProjectName = "LineItemS";

ProjectType = 0;

}

#endregion

#region 自定義屬性

public List<BufLineItem> LineItemS//泛型列表属性

{

get

{

return _lineItemS;

}

set

{

if (_lineItemS == value)

return;

_lineItemS = value;

}

}

#endregion

#region 自定義方法

public BufLineItem ItemOfLine(string _tmpLine)

{

BufLineItem _tmpItem = new BufLineItem();

//

foreach( BufLineItem _item in _lineItemS )

{

if (_item.LineName == _tmpLine)

{

_tmpItem = _item;

break;

}

}

//

return _tmpItem;

}

#endregion

//

}

还有一个把LineItemS转换成DataTable的方法,就不写详细代码啦,以便于客户端DataGrid或作为数据集操作处理

}

WCF服务端是这么写的

[OperationContract]

bool ExecuteBufLine(ref CBufLineItemS _tmpBufLineItemS, string ftype);

public bool ExecuteBufLine(ref CBufLineItemS _tmpBufLineItemS, string ftype)

{

bool _boRes = false;

try

{

//这里是作为数据库处理,得到数据,就不详细谢啦

_tmpBufLineItemS.LineItemS.Clear();//这里清空原有数据

BufLineItem _tmpBufLineItem = new BufLineItem() { LineName = _tmpLine, LinkMO = _tmpWO, LinkModel = _tmpLinkModel, OnLineSFCModel = _tmpOnLineModel, OnLineFeederList = _tmpOnLineBom, Type34F = _tmp34f };//这里是根据数据集处理结果生成新的

_tmpBufLineItemS.LineItemS.Add(_tmpBufLineItem);//添加数据集

}

_boRes = true;

}

catch

{

_boRes = false;

}

return _boRes;

}

基本操作就是上述的方式,实际工作中,当然比非面向对象的方式快捷多啦。具体代码部分以后再补上。

posted @ 2010-10-25 19:48 BruceZhou 阅读(116) 评论(0) 编辑

在很长一段时间里,我把系统服务作为WCF的宿主正式发布后,工作都很正常。知道一个比较单个功能函数耗时较多的服务发布后,经常会异常退出。很长一段时间里,我都认为是相应时间设置太短,一直客户端接受到异常。我好久时间里,都关注和改进这个函数的执行效率,以便于在更短时间内处理完毕。

一直到我看到了系统服务“事件日志”,有报错信息,才正确分析并找到错误点。因为我在调试的过程中,好长一段时间都是还没调试到错误,就报超时错误啦,一直不能找到错误点。

clip_image002

其中错误的详细如下

Application: *****.WCFService.WINHost.exe

Framework Version: v4.0.30319

Description: The process was terminated due to an unhandled exception.

Exception Info: System.AccessViolationException

Stack:

at System.Data.Common.UnsafeNativeMethods+ICommandText.Execute(IntPtr, System.Guid ByRef, System.Data.OleDb.tagDBPARAMS, IntPtr ByRef, System.Object ByRef)

at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForMultpleResults(System.Data.OleDb.tagDBPARAMS, System.Object ByRef)

at System.Data.OleDb.OleDbCommand.ExecuteCommandText(System.Object ByRef)

at System.Data.OleDb.OleDbCommand.ExecuteCommand(System.Data.CommandBehavior, System.Object ByRef)

at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(System.Data.CommandBehavior, System.String)

at System.Data.OleDb.OleDbCommand.ExecuteReader(System.Data.CommandBehavior)

at System.Data.OleDb.OleDbCommand.System.Data.IDbCommand.ExecuteReader(System.Data.CommandBehavior)

at System.Data.Common.DbDataAdapter.FillInternal(System.Data.DataSet, System.Data.DataTable[], Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)

at System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)

at System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, System.String)

at SFC.BasicClass4.SFCOraHelp.boExecuteSql(System.String, System.String[], System.String, System.Data.DataSet)

at SFC.BasicClass4.SFCBasic.dsExecuteSql(System.String, System.String[], System.String)

at SFC.Buffernet.WCFService.Service.CBufferNet.GetFeederListOfLine(System.String, System.String, System.String)

at DynamicClass.SyncInvoke GetFeederListOfLine (System.Object, System.Object[], System.Object[])

at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(System.Object, System.Object[], System.Object[] ByRef)

at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(System.ServiceModel.Dispatcher.MessageRpc ByRef)

at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean)

at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext, Boolean, System.ServiceModel.OperationContext)

at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext, System.ServiceModel.OperationContext)

at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult)

at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(System.IAsyncResult)

at System.Runtime.Fx+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)

at System.Runtime.AsyncResult.Complete(Boolean)

at System.Runtime.AsyncResult.Complete(Boolean, System.Exception)

at System.ServiceModel.Channels.FramingDuplexSessionChannel+TryReceiveAsyncResult.OnReceive(System.IAsyncResult)

at System.Runtime.Fx+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)

at System.Runtime.AsyncResult.Complete(Boolean)

at System.Runtime.AsyncResult.Complete(Boolean, System.Exception)

at System.ServiceModel.Channels.SynchronizedMessageSource+ReceiveAsyncResult.OnReceiveComplete(System.Object)

at System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(System.Object)

at System.ServiceModel.Channels.SocketConnection.FinishRead()

at System.ServiceModel.Channels.SocketConnection.AsyncReadCallback(Boolean, Int32, Int32)

at System.ServiceModel.Channels.OverlappedContext.CompleteCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

at System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)

at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

我仔细查找,找到了其中的函数GetFeederListOfLine,当我一眼看到这个函数的时候,我就知道是什么原因啦,肯定是数据库操作Sql语句的原因。

我仔细调试分析,找到原因。在Sql中要有不等的几个参数,当其中一个参数的值为空时,我写的处理函数就不会加在这个参数。前面的文章有介绍,在OleDb操作Oracle时,参数必须手动添加并赋值,我这里如果值是空,我写的处理函数就不会添加这个参数,致使报错。我在调试时,可以找到这个报错,也有Try处理过程,单在WCF中如果遇到这个问题,会直接退出,不会有任何报错。如果宿主是exe可执行程序,这个程序会直接退出,如果是系统服务,这个服务也会推出,但是状态显示时运行的,致使上面的运行按钮式可操作的,停止按钮式灰色的(正常运行后,运行按钮式灰色的,停止按钮式可操作的),但会在事件日志中记录这一异常错误。

posted @ 2010-10-25 19:48 BruceZhou 阅读(256) 评论(0) 编辑

这里我不写WCF怎么写代码的,网上有好多入门和提高的教程,我写的是怎么用,或者说我用到了WCF的什么。

刚开始写的时候,因为是为了Delphi开发而写的,所以算是一个远程函数调用,和COM+没有什么本质区别。就是在服务器上发布一个或多个函数,在客户端调用远程的函数,返回执行结果,当然包括数据集。1.我可以发布成网站形式的,和WebService差不多。单是开发起来,比WebService要可快速和简便,这是当时给我的感觉。这种发布方式没有正式应用的项目中。2.可以发布成一半exe可执行程式。这种发布方式当时给我的感觉很是惊艳。后来这种方式一至被我作为调试时的发布方式。3.可以注册成Windows系统服务,我学习这种方式的初衷是因为可以开机启动,不用登陆进系统。现在是我的WCF正式发布的方式。

因为最初的开发目的是为了Delphi可以调用,所以“远程函数调用”这种开发方式一致应用了好久,知道转到.netwinform开发,才转变了这种思想。

Delphi7是不支持直接调用WCF,生成WSDL中间语言的,我有到Delphi官方网站,找到最新的更新包WSDLImp.exe,和调用WCF的简介,当时还没有中文资料,因为Delphi7不能直接用可视化界面生成WSDL,只能用命令行调用,我还专门写了一个工具,省去了命令行的麻烦。其实Delphi已经更新到2005啦,可是我对Delphi7之后的所有版本都不敢兴趣,因为7之后的版本多是学习NET的IDE开发界面的,用着很不习惯,所以到现在,如果用到Delphi还是Delphi7,哈哈。在Win7出来后,才下的Delphi2010,因为Win7不支持Delphi7啦。

在讲些WCF初级应用所用到的发布方式。

1. 是IIS发布,和网站差不多,我问什么没用呢?、

还是因为Delphi调用的问题。Delphi生成WSDL后,只能识别IP地址的WSDL格式,不能识别 电脑名的WSDL格式,用IIS发布后,Delphi调用,中间一个地址一直是电脑名,不能转换成IP地址,所以才用到了exe发布和系统服务发布,因为她们都是用IP地址发布的,不会有电脑名的问题。虽然很久后找到了解决电脑名问题的方法,可是用系统服务发布挺好的,再也没有用IIS发布过WCF。

2. Exe可执行文件发布。只是在学习和调试的时候用。

3. 系统服务发布。在不用IIS发布这种方式后,我也没有打算用可执行文件发布作为正式的系统来用,因为考虑到开机登录问题,决定用系统服务来作为正式的发布。这三种方法几乎是同时学习的,因为在WCF的入门知识中就介绍啦。哈哈

4. 系统服务的应用。按照教程写的,WCF发布只能算是系统服务的一个简单应用,中间只要注意系统服务的名字就好啦,不是WCF服务的名字。因为默认的都是“Service1”,要改成自己用到的名字。只是在VS2010出来后,才有遇到了一个严重问题。在.Net3.5/.Net3.5SP1时,注册系统服务,都是用的.Net2.0的东西,到.Net4.0后才是用的.Net4.0的注册程序。.Net3.5写的只能用.Net2.0的注册程序,同样.Net4.0写的只能用.Net4.0的注册程序。不能混着用。

5. 在高级应用篇再介绍用到的 系统服务的日志排查WCF问题。

posted @ 2010-10-25 19:47 BruceZhou 阅读(359) 评论(0) 编辑

 

1. “maxReceivedMessageSize”

在用系统服务正式发布WCF后,很长一段时间,都很正常。直到一个比较复杂的功能开发。我的系统主要是和Oracle数据库开发,其中写了一个比较复杂的功能模块,返回很大的数据集,在客户端调用时一直报错,大约是“范围超过了65536”,从字面意思就很容易理解啦,maxReceivedMessageSize的默认值是65536,肯定某个方面超过了这个预设值。从网上查资料,果不其然,maxReceivedMessageSize这个选项就是表示中间传输的消息大小的。如果要传输的数据太大的话,就要增加这个值啦。我加了三个0,变成65536000,就不会出现开始的那个问题啦。当然,根据具体需要,你也可以改成其他更大或更小的值。

2. “<security mode="None" />”

在用TCP端口发布时,必须用这个选项。

3. “maxBufferSize”

修改了上述两个选项后,又在很长的一段时间,都很正常。直到一个问题出现。哈哈,这个问题的错误代码我没记住,主要的原因就是上传的数据太大啦,必须增大这个值。哈哈

4. “DataTable”作为返回值,这个没成功,后来改用DataSet作为返回值

5. “数组”作为返回值,这个正是用到啦,一些旧的系统还在用。现在当然不要啦。

6. “泛型”作为返回值,这个还要修改一些地方,得不偿失,我就改成自己写的类(包括数组或泛型 属性)作为返回值啦,

7. “自己写的类”做回返回值,现在主要的方式,也可以说是新开发应用的唯一的方式。

8. 千万别忘引用“System.ServiceModel

posted @ 2010-10-25 19:47 BruceZhou 阅读(284) 评论(0) 编辑

这里的第一个问题应该是为什么选择三层或多层架构?

1. 起初我选择三层架构的原因仅仅是不用安装Oracle客户端。、

我们这里许多系统都是要连接Oralce数据库的,又都是直接连接的Oracle,也就是2层架构。Oracle客户端约有180M,每台要用到我们系统的都要安装,又牵扯到用户的电脑权限管理,我们没有管理员权限,每次安装都要联系其他有权限的同事帮忙,所以想不用安装Oracle客户端该多好啊。

2. 当开始学习了一段三层架构后,才知道三层远不是不用安装Oracle客户端这么低级,她是一种非常庞大和精深的开发思想,多以又有进一步要求,想把我们的系统全部转换到三层架构的。

3. 又有进步后,才知道,三层和两层,各有利弊,并不是三层一定优于两层。不过这和我们的系统关系不大啦,因为我分析多次,我们的系统还是三层的好处要大于两层的。

当开发了一些三层架构的系统并应用后,这时才到问什么选择WCF的问题

1. 这里要谈一下我所用到三层架构的技术,主要包括DCOM(没有正式用到项目中,仅测试)。COM+,这个用到不少系统中,有些至今还在用,不过早已不是我负责的啦。WebService,就是指asp.net WebService,和架设网站一样。CORBA, 这个用到了正式的系统中,不过后来都改啦,CORBA是我在用WCF之前所用到的最好的功能,知道现在我还是觉的CORBA某些特点要优于WCF.

之上的4种三层技术除了WebService使用ASP.NET开发的外,其他都是Delphi开发的,因为当时的系统都是Delphi地。

2. DCOM和COM+,为什么不选择DCOM,而选择COM+?

因为我又用到了COM+,COM+的部署和开发比DCOM好多啦。DCOM的选择很快,约有不到一周的时间,因为找的一些例子都是COM+的,李维《Delphi5.x ADO/MTS/COM+高级程序设计篇》,是我的三层架构入门和提高最重要的书。不过很抱歉开始学习的是盗版书,一直到后来一位前辈离职的时候,把他的一本正版书送给了我,我才视为经典收藏起来,在后来几年不时拿出瞻仰一番,知道去年搬家,把一些不用的书放在朋友家里,才一年多没有拿来看看。

COM+开发已经用的挺成熟啦,用到了一些ODM系统中(多是同事开发的),但是她的客户端部署时对权限要求交高,所以不是很想用她开发整个系统,不可否认的是,通过COM+的学习在三层架构学习中,给我的很大帮助,和奠定了基础,才成有后来的WCF的快速入门。

3. COBRA,因为当时一直用的Delphi开发,所以一直想找一种比COM+部署更简便的三层构(仅仅是部署方便的问题,不是技术问题),才找到了COBRA,开发了一些东西,对大的部署简单很是上心。当时还写了2篇文章发到Delphibbs大富翁上,主要写的是怎么用Delphi6+7组合来开发COBRA并部署,还有几位大富翁发信来问。因为她开发来比COM+要复杂,还要受到中间语言的限制,所以没有正式用到项目中。不过到现在还是觉得她的部署简单和自动负载平衡是很棒的。

4. Asp.net WebService,这是在COM+后接触的,比CORBA家要早一段时间。当时还是VS2003, 算是.net入门吧。我一直觉得我学习.net是以开发Asp.netWebService开始的,当时的客户端还是Delphi开发地。因为主要是和Oracle数据库开发,还写了一篇怎么用XML格式传输数据集,并Delphi调用处理。一直到WCF,还开发了几个用XML格式传输数据集,并Delphi客户端调用的服务。

不选择她还是因为部署问题,到不算是真的部署问题。她的部署也是非常简单的,和ASP.NET网站一样。主要是因为她只能HTTP调用,我所开发的系统客户端,还是前面的问题,权限限制,许多时候要用代理才能上网,并许多客户机的HTTP代理是固定的,这就杯具啦,有代理就不能连接WebService啦。当然,还有许多流程或其他可以解决这个问题,不过们部署起来越简单岂不越好。

5. 一直到我遇到WCF, 才发现这就是我要的东西。当时因为是看到了VS2008的算是广告吧,一直在关注2008,才发现的这个WCF。知道学习VS2008+WCF好久,才知道VS2005+net3.0也是可以开发WCF的。当时要用WCF的主要原因是1.她能TCP端口发布,不受http代理的影响2.她是新技术,我觉得第2点倒是占主要的,哈哈。

6. 再简单介绍一些我.NET的学习历史。我是因为Asp.net WebService才学习.Net的,学习用到VS2003,当时客户端都是Delphi,对.net的WinForm开发没怎么上心。VS2005几乎没用过。到需要.NET或者说转到.Net开发就是VS2008啦。

posted @ 2010-10-25 19:45 BruceZhou 阅读(665) 评论(0) 编辑

最近用到了EntLib,在自己电脑上Windows7 x64,开发的ExceptionHandlingApplicationBlock模块竟然不能用,随后在网上也没找到答案。

具体情况是,可以记录成TXT,而记录成window日志,没有成功,也没有报错,就是在事件查看器中找不到。看到网上有提示可能是Win7的权限问题,随后右键点击exe,“以管理员身份运行”,竟然运行成功。随后有新建了一个例子,测试ExceptionHandlingApplicationBlock功能,竟然可以用啦,有些诡异,哈哈。

     从网上没有找到具体答案,特记录与君共勉。

posted @ 2010-10-15 21:00 BruceZhou 阅读(29) 评论(0) 编辑

最近帮朋友写了个小程序,用到了Sqlite,和其他如Oracle,SqlServer等还是有点区别的,记录一下。

1. 有Sqlite的.net2.0 3.5的驱动,安装后和ole驱动一样用法,大有一些以SQLite***开头的和ole对应一样的类。

连接字符串例如“Data Source=文件名;Pooling=true;FailIfMissing=false”。Pooling=true;FailIfMissing=false有对应的意义,google一下就有啦,我到没有用到这两个设置。

2.就是Datetime类型,和其他有些区别。

他的默认格式是ISO 8601标准字符串,是标准时间。

有内部函数,如下面的列表。

这里有3个注意的地方:

  1. datetime(‘now’),注意这里的单引号是必须带着的,相当于.Net中的DateTime.Now,Oracle中的sysdate,表示当前时间,不过是标准时间, datetime(‘now’,‘+8 hour’)才是北京时间的当前时间。
  2. 插入式直接用字符串insert into table1(datetime) values(‘2010-01-29 19:00:01’),必须用”YYYY-MM-DD HH24:MI:SS”的格式
  3. where 条件也一样 where datetime1 <= ‘2010-01-29 19:00:01’

 

Home » 未分类 » Sqlite日期和时间函数不求人 Sqlite日期和时间函数不求人
Posted by admin on 星期四 18 十二 2008
SQLite 包含了如下时间/日期函数:
datetime()…………………..产生日期和时间
date()………………………产生日期
time()………………………产生时间
strftime()………………….. 对以上三个函数产生的日期和时间进行格式化
datetime()的用法是:datetime(日期/时间,修正符,修正符…)
date()和time()的语法与datetime()相同。
在时间/日期函数里可以使用如下格式的字符串作为参数:
YYYY-MM-DD
YYYY-MM-DD HH:MM
YYYY-MM-DD HH:MM:SS
YYYY-MM-DD HH:MM:SS.SSS
HH:MM
HH:MM:SS
HH:MM:SS.SSS
now
其中now是产生现在的时间。
举例(写这个笔记的时间是2006年10月17日晚8点到10点,测试环境:SQLite 2.8.17,WinXP,北京时间):
例1.
select datetime(’now’);
结果:2006-10-17 12:55:54
例2.
select datetime(’2006-10-17′);
结果:2006-10-17 12:00:00
例3.
select datetime(’2006-10-17 00:20:00′,’+1 hour’,’-12 minute’);
结果:2006-10-17 01:08:00
例4.
select date(’2006-10-17′,’+1 day’,’+1 year’);
结果:2007-10-18
例5.
select datetime(’now’,’start of year’);
结果:2006-01-01 00:00:00
例6.
select datetime(’now’,’start of month’);
结果:2006-10-01 00:00:00
例7.
select datetime(’now’,’start of day’);
结果:2006-10-17 00:00:00
例8.
select datetime(’now’,’+10 hour’,’start of day’,’+10 hour’);
结果:2006-10-17 10:00:00
例9.
select datetime(’now’,’localtime’);
结果:2006-10-17 21:21:47
例10.
select datetime(’now’,’+8 hour’);
结果:2006-10-17 21:24:45
例3中的+1 hour和-12 minute表示可以在基本时间上(datetime函数的第一个参数)增加或减少一定时间。
例5中的start of year表示一年开始的时间。
从例8可以看出,尽管第2个参数加上了10个小时,但是却被第3个参数“start of day”把时间归零到00:00:00,随后的第4个参数在00:00:00
的基础上把时间增加了10个小时变成了10:00:00。
例9 把格林威治时区转换成本地时区。
例10把格林威治时区转换成东八区。
strftime()函数可以把YYYY-MM-DD HH:MM:SS格式的日期字符串转换成其它形式的字符串。
strftime() 的语法是strftime(格式, 日期/时间, 修正符, 修正符, …)
它可以用以下的符号对日期和时间进行格式化:
%d 月份, 01-31
%f 小数形式的秒,SS.SSS
%H 小时, []

3. 其他的常用语法是Sql的标准语法,如绑定参数等,暂还没发现其他不同的地方。

posted @ 2010-01-29 22:07 BruceZhou 阅读(1437) 评论(0) 编辑