您的位置:首页 > 其它

业务平台和软件价构的一些想法

2008-08-19 22:57 281 查看
一、系统架构设计
1[/b].1系统整体架构及各结构层描述[/b]
软件系统结构分为三层,从下至上分别为:数据访问层、业务逻辑层、表示层,如图所示:

表示层(WinForm[/b])[/b]
表示层(WebForm[/b])[/b]
业务逻辑层[/b]
数据访问层([/b]微软企业库提供的数据库访问方法)[/b]
SqlServer2005
DB2
Oracle
。。。。。。

1.1.1数据访问层:
有时候也称为是持久层,其功能主要是负责数据库的访问。简单的说法就是实现对数据表的Select,Insert,Update,Delete的操作。
利用微软企业库的DataAccess Application Block实现对多类型数据库操作,可以访问SqlServer、Oracle、OleDB等类型数据库。DataAccess Application Block 不是ADO.NET的替代品,它是对ADO.NET的补充。DataAccess Application Block的优点在于它可以使用相同的代码去访问不同类型的数据库,比如我们的应用程序从Sql Server上转到Oracle,那么使用DataAccess Application Block 可以让你不需要修改任何代码而达到上述功能。
数据访问层基类:新建类库Mesnac.Common.DataAccess.SystemBase.dll ,引用Microsoft.Practices.EnterpriseLibrary.Common.dll、Microsoft.Practices.EnterpriseLibrary.Data.dll、Microsoft.Practices.ObjectBuilder.dll三个类库。数据访问层基类利用微软企业库实现对数据库的具体操作,所有的数据访问层的类库都要继承这个基类。具体代码如下:
using System;
using System.Data;
using System.Data.Common;
using System.Data.OleDb;
using System.Collections;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;
using Microsoft.Practices.EnterpriseLibrary.Data.Oracle;
using Mesnac.Common;

namespace Mesnac.Common.DataAccess
{
public class SystemBase :MarshalByRefObject
{
//批执行SQL语句
public string ExecSQL(string[] ExecSql, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase(ConnectionString, HelperType);

using ( DbConnection conn = db.CreateConnection())
{
//打开连接
conn.Open();
//创建事务
DbTransaction trans = conn.BeginTransaction();
try
{
for (int i = 0; i < ExecSql.GetUpperBound(0) + 1; i++)
db.ExecuteNonQuery(CommandType.Text, ExecSql[i].ToString());
//都执行成功则提交事务
trans.Commit();
return string.Empty;
}
catch (Exception ex)
{
//发生异常,事务回滚
trans.Rollback();
return ex.Message;
}
finally
{
//关闭连接
conn.Close();
}
}
}

//通过SQL语句填充DataSet(这里为什么要用数组类型的表名)
public void FillDataSetBySQL(DataSet Ds, string[] TableNames, string Sql, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase(ConnectionString, HelperType);
DataSet tempDs = db.ExecuteDataSet(CommandType.Text, Sql);

for (int i = 0; i < TableNames.GetUpperBound(0) + 1; i++)
{
tempDs.Tables[0].TableName = TableNames[i].ToString();
Ds.Tables.Add(tempDs.Tables[0].Copy());
}
}

//获取数据库实例
public Database GetDataBase(string ConnectionString, DataBaseType HelperType)
{
Database db = null;
switch(HelperType)
{
case DataBaseType.SqlServer: //创建SqlServer数据库
db = new SqlDatabase(ConnectionString);
break;
case DataBaseType.Oracle: //创建Oracle数据库
db = new OracleDatabase(ConnectionString);
break;
case DataBaseType.Oledb: //创建Oledb数据库
db = new GenericDatabase(ConnectionString, OleDbFactory.Instance);
break;
}
return db;
}

public IDataReader GetDataReaderBySQL(string Sql, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase(ConnectionString, HelperType);
return db.ExecuteReader(CommandType.Text, Sql);
}

public DataSet GetDataSetBySQL(string Sql, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase( ConnectionString, HelperType);
return db.ExecuteDataSet(CommandType.Text,Sql);
}

//根据Sql语句获得某值
public object GetValueBySQL(string Sql, int FieldIndex, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase(ConnectionString, HelperType);
IDataReader dr = db.ExecuteReader(CommandType.Text, Sql);
if (dr.Read())
return dr[FieldIndex];
else
return null;
}

//根据Sql语句获得某值
public object GetValueBySQL(string Sql, string FieldName, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase(ConnectionString, HelperType);
IDataReader dr = db.ExecuteReader(CommandType.Text, Sql);
if (dr.Read())
return dr[FieldName];
else
return null;
}

//根据Sql语句获得Hashtable类型的数据
public Hashtable GetValueListBySQL(string Sql, string ConnectionString, DataBaseType HelperType)
{
Hashtable ht = new Hashtable();
Database db = GetDataBase(ConnectionString, HelperType);
IDataReader dr = db.ExecuteReader(CommandType.Text, Sql);
if (dr.Read())
{
for (int i = 0; i < dr.FieldCount; i++)
ht.Add(dr.GetName(i), dr.GetValue(i));
return ht;
}
else
return null;
}

//更新数据集
public string UpdateDataSet(DataSet Ds, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase(ConnectionString, HelperType);
DbConnection myConn = db.CreateConnection();
myConn.Open();
DbTransaction myTrans = myConn.BeginTransaction();
try
{
foreach (DataTable dt in Ds.Tables)
{
//判断该表是否要保存
if (dt.ExtendedProperties["Saved"] != null && dt.ExtendedProperties["Saved"].ToString() == "1")
{
//新增Command
string colName = ""; string parName = "";
foreach (DataColumn col in dt.Columns)
{
if (col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1")
{
colName = colName + col.ColumnName + ",";
parName = parName + "@" + col.ColumnName + ",";
}
}
string insSql = "insert into " + dt.TableName + "( " + colName.TrimEnd(",".ToCharArray()) + " ) values (" + parName.TrimEnd(",".ToCharArray()) + ")";
DbCommand insCommand = db.GetSqlStringCommand(insSql);
insCommand.Connection = myConn;
insCommand.Transaction = myTrans;

foreach (DataColumn col in dt.Columns)
{
if (col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1")
{
db.AddInParameter(insCommand, "@" + col.ColumnName, GetDbType(col.DataType), col.ColumnName, DataRowVersion.Default);
}
}

//删除Command
string keyWordColName = "";
if (dt.ExtendedProperties["KeyWord"] != null && dt.ExtendedProperties["KeyWord"].ToString() != "")
{
string[] strArr = dt.ExtendedProperties["KeyWord"].ToString().Split(",".ToCharArray());
for (int i = 0; i < strArr.GetUpperBound(0) + 1; i++)
keyWordColName = keyWordColName + strArr[i] + " = @" + strArr[i] + " AND ";
}

keyWordColName = keyWordColName.TrimEnd(" AND ".ToCharArray());
string delSql = "delete from " + dt.TableName + " where " + keyWordColName.TrimEnd(",".ToCharArray()) + "";
DbCommand delCommand = db.GetSqlStringCommand(delSql);
delCommand.Connection = myConn;
delCommand.Transaction = myTrans;
if (dt.ExtendedProperties["KeyWord"] != null && dt.ExtendedProperties["KeyWord"].ToString() != "")
{
string[] strArr = dt.ExtendedProperties["KeyWord"].ToString().Split(",".ToCharArray());
for (int i = 0; i < strArr.GetUpperBound(0) + 1; i++)
db.AddInParameter(delCommand, "@" + strArr[i], GetDbType(dt.Columns[strArr[i]].DataType), strArr[i], DataRowVersion.Default);
}

//更新Command
string savedColName = "";
foreach (DataColumn col in dt.Columns)
{
if ((col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1"))
savedColName = savedColName + col.ColumnName + "= @" + col.ColumnName + ",";
}

string updSql = "update " + dt.TableName + " set " + savedColName.TrimEnd(",".ToCharArray()) + " where " + keyWordColName + "";
DbCommand updCommand = db.GetSqlStringCommand(updSql);
updCommand.Connection = myConn;
updCommand.Transaction = myTrans;

foreach (DataColumn col in dt.Columns)
{
if (col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1")
{
db.AddInParameter(updCommand, "@" + col.ColumnName, GetDbType(col.DataType), col.ColumnName, DataRowVersion.Default);
}
}
db.UpdateDataSet(Ds, dt.TableName, insCommand, updCommand, delCommand, myTrans);
}
}
myTrans.Commit();
Ds.AcceptChanges();
return string.Empty;
}
catch (Exception e)
{
myTrans.Rollback();
return e.Message;
}
finally
{
myConn.Close();
}
}

private DbType GetDbType(Type colDataType)
{
DbType dbType = DbType.String;
if (colDataType == typeof(String))
dbType = DbType.String;
else if (colDataType == typeof(DateTime))
dbType = DbType.DateTime;
else if (colDataType == typeof(Boolean))
dbType = DbType.Boolean;
else if (colDataType == typeof(Byte))
dbType = DbType.Byte;
else if (colDataType == typeof(Decimal))
dbType = DbType.Decimal;
else if (colDataType == typeof(Double))
dbType = DbType.Double;
else if (colDataType == typeof(Guid))
dbType = DbType.Guid;
else if (colDataType == typeof(Int16))
dbType = DbType.Int16;
else if (colDataType == typeof(Int32))
dbType = DbType.Int32;
else if (colDataType == typeof(Int64))
dbType = DbType.Int64;
else if (colDataType == typeof(Object))
dbType = DbType.Object;
else if (colDataType == typeof(SByte))
dbType = DbType.SByte;
else if (colDataType == typeof(Single))
dbType = DbType.Single;
else if (colDataType == typeof(UInt16))
dbType = DbType.UInt16;
else if (colDataType == typeof(UInt32))
dbType = DbType.UInt32;
else if (colDataType == typeof(UInt64))
dbType = DbType.UInt64;

return dbType;
}

//更新数据集(重载)
public string UpdateDataSet(DataSet Ds, string[] BeforeSavedSql, string[] AfterSavedSql, string ConnectionString, DataBaseType HelperType)
{
Database db = GetDataBase(ConnectionString, HelperType);
DbConnection myConn = db.CreateConnection();
myConn.Open();
DbTransaction myTrans = myConn.BeginTransaction();
try
{
//保存表更新之前执行的代码
if (BeforeSavedSql != null)
{
DbCommand myCommand = myConn.CreateCommand();
myCommand.Transaction = myTrans;
myCommand.Connection = myConn;
for (int i = 0; i < BeforeSavedSql.GetUpperBound(0) + 1; i++)
{
myCommand.CommandText = BeforeSavedSql[i];
myCommand.ExecuteNonQuery();
}
}

foreach (DataTable dt in Ds.Tables)
{
//判断该表是否要保存
if (dt.ExtendedProperties["Saved"] != null && dt.ExtendedProperties["Saved"].ToString() == "1")
{
//新增Command
string colName = ""; string parName = "";
foreach (DataColumn col in dt.Columns)
{
if (col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1")
{
colName = colName + col.ColumnName + ",";
parName = parName + "@" + col.ColumnName + ",";
}
}
string insSql = "insert into " + dt.TableName + "( " + colName.TrimEnd(",".ToCharArray()) + " ) values (" + parName.TrimEnd(",".ToCharArray()) + ")";
DbCommand insCommand = db.GetSqlStringCommand(insSql);
insCommand.Connection = myConn;
insCommand.Transaction = myTrans;

foreach (DataColumn col in dt.Columns)
{
if (col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1")
{
db.AddInParameter(insCommand, "@" + col.ColumnName, GetDbType(col.DataType), col.ColumnName, DataRowVersion.Default);
}
}

//删除Command
string keyWordColName = "";
if (dt.ExtendedProperties["KeyWord"] != null && dt.ExtendedProperties["KeyWord"].ToString() != "")
{
string[] strArr = dt.ExtendedProperties["KeyWord"].ToString().Split(",".ToCharArray());
for (int i = 0; i < strArr.GetUpperBound(0) + 1; i++)
keyWordColName = keyWordColName + strArr[i] + " = @" + strArr[i] + " AND ";
}

keyWordColName = keyWordColName.TrimEnd(" AND ".ToCharArray());
string delSql = "delete from " + dt.TableName + " where " + keyWordColName.TrimEnd(",".ToCharArray()) + "";
DbCommand delCommand = db.GetSqlStringCommand(delSql);
delCommand.Connection = myConn;
delCommand.Transaction = myTrans;
if (dt.ExtendedProperties["KeyWord"] != null && dt.ExtendedProperties["KeyWord"].ToString() != "")
{
string[] strArr = dt.ExtendedProperties["KeyWord"].ToString().Split(",".ToCharArray());
for (int i = 0; i < strArr.GetUpperBound(0) + 1; i++)
db.AddInParameter(delCommand, "@" + strArr[i], GetDbType(dt.Columns[strArr[i]].DataType), strArr[i], DataRowVersion.Default);
}

//更新Command
string savedColName = "";
foreach (DataColumn col in dt.Columns)
{
if ((col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1"))
savedColName = savedColName + col.ColumnName + "= @" + col.ColumnName + ",";
}

string updSql = "update " + dt.TableName + " set " + savedColName.TrimEnd(",".ToCharArray()) + " where " + keyWordColName + "";
DbCommand updCommand = db.GetSqlStringCommand(updSql);
updCommand.Connection = myConn;
updCommand.Transaction = myTrans;

foreach (DataColumn col in dt.Columns)
{
if (col.ExtendedProperties["Saved"] != null && col.ExtendedProperties["Saved"].ToString() == "1")
{
db.AddInParameter(updCommand, "@" + col.ColumnName, GetDbType(col.DataType), col.ColumnName, DataRowVersion.Default);
}
}
db.UpdateDataSet(Ds, dt.TableName, insCommand, updCommand, delCommand, myTrans);
}
}

//保存表更新之后执行的代码
if (AfterSavedSql != null)
{
DbCommand myCommand = myConn.CreateCommand();
myCommand.Transaction = myTrans;
myCommand.Connection = myConn;
for (int i = 0; i < AfterSavedSql.GetUpperBound(0) + 1; i++)
{
myCommand.CommandText = AfterSavedSql[i];
myCommand.ExecuteNonQuery();
}
}

myTrans.Commit();
Ds.AcceptChanges();
return string.Empty;
}
catch (Exception e)
{
myTrans.Rollback();
return e.Message;
}
finally
{
myConn.Close();
}
}
}
}
注[/b]:此基类继承自MarshalByRefObject,所有继承自此基类的数据访问层类库当布置到.NetRemoting服务器端时候,都必须继承自MarshalByRefObject,为以后做成分布式系统做基础。为什么要继承自MarshalByRefObject呢?
应用程序域是一个操作系统进程中一个或多个应用程序所驻留的分区。同一应用程序域中的对象直接通信。不同应用程序域中的对象的通信方式有两种:一种是跨应用程序域边界传输对象副本,一种是使用代理交换消息。MarshalByRefObject 是通过使用代理交换消息来跨应用程序域边界进行通信的对象的基类。不是从 MarshalByRefObject 继承的对象根据值隐式封送。当远程应用程序引用根据值封送的对象时,将跨应用程序域边界传递该对象的副本。
MarshalByRefObject 对象在本地应用程序域的边界内可直接访问。远程应用程序域中的应用程序首次访问 MarshalByRefObject 时,会向该远程应用程序传递代理。对该代理后面的调用将封送回驻留在本地应用程序域中的对象。
当跨应用程序域边界使用类型时,类型必须是从 MarshalByRefObject 继承的,而且由于对象的成员在创建它们的应用程序域之外无法使用,所以不得复制对象的状态。

1.1.2业务逻辑层:
无疑是系统架构中体现核心价值的部分。它的关注点主要集中在业务规则的制定、业务流程的实现等与业务需求有关的系统设计,也即是说它是与系统所应对的领域(Domain)逻辑有关,很多时候,我们也将业务逻辑层称为领域层。业务逻辑层在体系架构中的位置很关键,它处于数据访问层与表示层中间,起到了数据交换中承上启下的作用。由于层是一种弱耦合结构,层与层之间的依赖是向下的,底层对于上层而言是“无知”的,改变上层的设计对于其调用的底层而言没有任何影响。如果在分层设计时,遵循了面向接口设计的思想,那么这种向下的依赖也应该是一种弱依赖关系。因而在不改变接口定义的前提下,理想的分层式架构,应该是一个支持可抽取、可替换的“抽屉”式架构。正因为如此,业务逻辑层的设计对于一个支持可扩展的架构尤为关键,因为它扮演了两个不同的角色。对于数据访问层而言,它是调用者;对于表示层而言,它却是被调用者。依赖与被依赖的关系都纠结在业务逻辑层上,如何实现依赖关系的解耦,则是除了实现业务逻辑之外留给设计师的任务。
1.1.3表示层:
是系统的UI部分,负责使用者与整个系统的交互。在这一层中,理想的状态是不应包括系统的业务逻辑。表示层中的逻辑代码,仅与界面元素有关。

1[/b].2分层式系统架构优缺点[/b]
分层式结构究竟其优势何在?
1、开发人员可以只关注整个结构中的其中某一层;
2、可以很容易的用新的实现来替换原有层次的实现;
3、可以降低层与层之间的依赖;
4、有利于标准化;
5、利于各层逻辑的代码复用。
概括来说,分层式设计可以达至如下目的:分散关注、松散耦合、逻辑复用、标准定义。
1、分散关注:一个好的分层式结构,可以使得开发人员的分工更加明确。一旦定义好各层次之间的接口,负责不同逻辑设计的开发人员就可以分散关注,齐头并进。例如UI人员只需考虑用户界面的体验与操作,领域的设计人员可以仅关注业务逻辑的设计,而数据库设计人员也不必为繁琐的用户交互而头疼了。每个开发人员的任务得到了确认,开发进度就可以迅速的提高。
2、松散耦合的好处是显而易见的。如果一个系统没有分层,那么各自的逻辑都紧紧纠缠在一起,彼此间相互依赖,谁都是不可替换的。一旦发生改变,则牵一发而动全身,对项目的影响极为严重。降低层与层间的依赖性,既可以良好地保证未来的可扩展,在复用性上也是优势明显。每个功能模块一旦定义好统一的接口,就可以被各个模块所调用,而不用为相同的功能进行重复地开发。
进行好的分层式结构设计,标准也是必不可少的。只有在一定程度的标准化基础上,这个系统才是可扩展的,可替换的。而层与层之间的通信也必然保证了接口的标准化。
分层式结构缺陷:
1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。
2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

1[/b].3通过设置系统实现集中式和分布式两种体系架构[/b]
[/b]集中式架构是相对于分布式架构而言的一种体系架构,软件的分层模式和软件的整体结构以及软件功能都没有改变,只是部署方式改变了,相比较分布式系统而言,只是部署上没有了中间层(应用程序服务器),客户端直接通过本地数据访问层访问数据库服务器,我也找不到合适的词来为它命名,暂且称为集中式系统吧;而分布式架构的系统的客户端通过访问中间层(应用程序服务器)开放的服务(数据访问层的类库)去访问数据库服务器,系统通过一个设置去决定是否访问中间层。分布式架构一般适合在各地都有分公司、数据量很大、数据访问很频繁的规模比较大的企业,分布式架构只有用在这样的企业中,它的优势才能得以体现;相反,集中式系统一般适用在规模比较小的企业中,一般应用在局域网中,下面具体讲述一下系统实现:
1.3.1利用.Net Remoting实现分布式体系结构
首先介绍两个概念:
1、Remoting:一种分布式处理方式,也可将它看作是DCOM的一种升级,它改善了很多功能,并极好的融合到.Net平台下。.NET Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。
在Remoting中是通过通道(channel)来实现两个应用程序域之间对象的通信的。
首先,客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象。这就提供一种可能性,即以服务的方式来发布服务器对象。远程对象代码(数据访问层)可以运行在服务器上(如服务器激活的对象和客户端激活的对象),然后客户端再通过Remoting连接服务器,获得该服务对象并通过序列化在客户端运行。
在Remoting中,对于要传递的对象,设计者除了需要了解通道的类型和端口号之外,无需再了解数据包的格式。但必须注意的是,客户端在获取服务器端对象时,并不是获得实际的服务端对象,而是获得它的引用。这既保证了客户端和服务器端有关对象的松散耦合,同时也优化了通信的性能。
2、分布式系统:分布式数据库系统的数据在逻辑上是统一的,而在物理上却是分散的。与集中式数据库相比它有如下主要优点:
• 解决组织机构分散而数据需要相互联系的问题。
• 均衡负载。负载在各处理机间分担,可避免临界瓶颈。
• 可靠性高。数据分布在不同场地,且存有多个副本,即使个别场地发生故障,不致引起整个系统的瘫痪。
• 可扩充性好。当需要增加新的相对自主的组织单位时,可在对当前机构影响最小的情况下进行扩充。

综合以上两个概念可以知道用Remoting实现分布式系统是有很大优点而且在技术上也是可行的。图1-3-1是系统的一个分布式架构图:

客户端 客户端 客户端 客户端 客户端 客户端 客户端

[/b][/b] [/b]
应用程序服务器 应用程序服务器 应用程序服务器

[/b][/b]
数据库服务器 数据库服务器
图1-3-1 分布式系统架构图
总体的数据访问方式就是:分布在不同地方的客户端通过分布在不同地方的应用程序服务器来访问数据库服务器。客户端可以配置具体某一个要访问的应用程序服务器。
应用程序服务器访问数据库服务器方式:数据库可以放在同一台数据库服务器上,也可以放在不同的数据库服务器上,但需要注意的是要进行数据同步,数据库服务器有固定的IP,远程应用程序服务器通过数据库服务器的固定IP和开放的端口来访问数据库服务器。
客户端访问应用程序服务器的方式:把数据访问层的类库部署在分布在不同地方的应用程序服务器上,各个应用程序服务器有固定的IP。利用.Remoting服务器端组件注册服务器通道,以服务的方式发布对象。客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象。这就提供一种可能性,即以服务的方式来发布服务器对象。远程对象代码(数据访问层)可以运行在服务器上(如服务器激活的对象和客户端激活的对象),然后客户端再通过Remoting连接服务器,获得该服务对象并通过序列化在客户端运行。
1.3.2集中式架构系统的实现
图1-3-2是系统的一个集中式架构图:

客户端 客户端 客户端 客户端 客户端 客户端 客户端

总体的数据访问方式就是:分布在不同地方的客户端通过本地的数据访问层直接访问数据库服务器。

总之,远程处理是.NET框架提供的一项强大的技术,利用它可以使位于任何位置的应用程序互相通信,这些应用程序可能在同一台计算机上运行,也可能位于同一局域网中的不同计算机上,或者位于相隔万里的有巨大差异的网络中。
使用.NET Remoting技术结合微软企业库的DAB(DataAccess Application Block)能够高效、可靠地解决这两方面的问题。具体表现为,在C#中通过使用.Net远程处理框架能够方便地解决数据、命令远程传递问题;C#通过微软企业库的DAB对数据库进行操作,使分布式数据库系统中对数据库的各种操作变得高效、可靠,同时易于解决数据一致性问题,而且可以访问多种数据库。

二、商业物流平台
以前所做平台是商业物流平台,一些内置引擎有很大的行业针对性,可能和Mes平台在某些方面有相同点,但很大程度上应该是不同的。
在以前所做的平台技术体系中,基础平台有其明确的定义和清晰的内容。主要包括用以支撑业务服务所定义的组件标准,以下是以前所做业务平台大概包含的内容:
1、多通道访问引擎:主要通过智能客户端和短信群发解决如何通过手机、PDA、邮件等多种访问方式来访问业务组件所提供的功能和获取存储在数据库中的信息。
2、消息引擎:解决流程驱动下人机交互过程中,将各流程节点的操作提示和系统通知、预警等信息发送到用户的消息中。
3、发布引擎:用以解决将按照业务服务标准进行封装的业务组件,快捷的发布到业务系统之中,并保障不同的组件之间无缝的信息集成与共享,发布引擎同时屏蔽了不同厂商的应用服务器的技术细节的差异。
4、流程引擎:是业务流程中的控制流程,根据已定义的流程路线依据不同的规则,将任务有效的分配给人工处理或者交由预定义的自动节点进行处理。流程引擎同时提供对流程运行状况的监控与管理。
5、集成引擎:集成引擎更像一个信息的路由器,它能根据已定义的异构系统之间数据交换的映射规则,将数据中转和路由到需要集成的系统中。集成引擎是可以通过业务操作触发驱动或者按照时间规则进行调度执行。
6、规则引擎:规则引擎可以用来定义复杂的业务逻辑,流程跳转规则、数据转换规则、数据筛选规则、事务预警规则、任务调度规则等多种包含复杂逻辑关系的处理,都可以统一的通过规则引擎进行解析。
7、分析引擎:通过自定义报表和万能报表,能够提供对数据库数据进行报表展现前的数据加工,分析引擎可以将多个相关的二维数据表转换成三维表结构,同时也可以提供结果集级别的分类汇总、小记、汇总和数据筛选等特性。提供多类型数据库操作。而且还提供了可视化的报表数据向导,报表样式向导,参照引入等功能,能够引导用户快速简单的设计出复杂的报表.,将数据仓库(DW)、联机分析处理(OLAP)、数据挖掘(DM)等技术与资源管理系统(ERP)结合起来应用于商业活动实际过程当中。
8、安全引擎:解决应用程序功能的访问权限,数据记录访问权限,组织架构隔离权限等数据安全性问题。
9、工作流审批引擎:解决各业务数据的流程审批。按企业实际的工作流,设置各级流程审批顺序,以及在各个审批环节中哪些角色去审批数据。
10、数据访问引擎:利用微软企业库的数据访问组件解决SQL Server,DB2,Oracle等主流数据库SQL语法差异的屏蔽层,按照KSQL语法编写的SQL语句能够自动翻译成不同数据库的SQL语句。
11、表单设计引擎:
可以像微软的IDE一样的界面,用户可以自己拖拽控件到界面上,所有的控件的属性都保存在后台数据库中,发布表单后,系统直接可以看到所设计的表单单据。这样做的好处是:
1、 加快了开发速度
2、 减少Bug
3、 让开发人员的注意力关注在逻辑层,不必再做重复的代码复制。
由于对当前的平台不是太理解,只感觉实现了在数据库表中定义字段,然后根据字段在界面加载的时候,把相对应的字段在界面上画出控件;而且只能实现单表的输入,还不能实现主从表以及更复杂的表单;不能实现像IDE那样任意拖拉控件来设计表单,如果想实现真正的业务平台化,还有待进一步开发。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: