元数据大概就是这样的
<WawaCRM>
<模块 name="模块名" desc="模块描述">
<动作 name="动作名" desc="动作描述">
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
</动作>
<动作 name="动作名" desc="动作描述">
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
</动作>
</模块>
<模块 name="模块名" desc="模块描述">
<动作 name="动作名" desc="动作描述">
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
</动作>
<动作 name="动作名" desc="动作描述">
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
<存储过程>存储过程名字</存储过程>
<容器ID>容器ID</容器ID>
</动作>
</模块>
</WawaCRM>
一个系统包含多个模块,一个模块包含多个动作,一个动作是由多个存储过程和容器来实现的。
因为存储过程比较多,在企业管理器里查找修改存储过程不方便,所以首先要写一个工具来统一管理存储过程。大概最后是这样的。打开这个小工具,首先出现的是【模块下拉菜单】,选中一个模块,【动作下拉菜单】就有内容了,选定动作,这个动作里包含的【存储过程下来菜单】就填充了,然后选择存储过程,在一个编辑框里就显示了存储过程的内容,在这里修改存储过程,并点击【更新存储过程】按钮,这时候存储过程就更新到数据库了。如果当时元数据里提供的存储过程在数据库里没有,系统会让【新建存储过程】变成可用,你直接在文本框里开发t-sql的存储过程,单击那个按钮就保存到数据库里了。这个功能是需要实现给小工具设置数据库连接字符串。这个文本框呢,最好能够和查询分析器一样,能够检查T-SQL的正确性,能够支持T-SQL语法高亮显示,还能够支持自动格式化代码的缩进和大小写。
然后呢,每个存储过程都对应一个有对应的XML元数据,我们在点击了【存储过程下拉菜单】的时候,在文本框里显示了存储过程的内容,这时候有个【更新元数据】的按钮,就会自动在余预先设置的目录里生成此存储过程对应的元数据,因为存储过程不能重名,而容器ID也不能重名,所以默认的XML元文件名就是“容器ID.config“这一切要求自动生成。然后呢,我们的CMP架构需要改一些,在application_start方法里检索指定目录里的所有.config文件,生成相应的容器并缓存起来,以便业务层使用,不必把所有的元数据都放在web.config里,那样很乱。
持久对象的实体类也要自动生成,我们也集成到这个工具里面,选择了数据库的表后,就可以生成实体类了,但是大多数生成的实体类需要做一些修改,但是基本的实体的属性都已经就位了,需要做的就是偶尔增加一两个属性,或者覆写FinalizeData()方法就可以了。比如说一个Product的实体类,可能需要有DataTable类型的images属性,这个属性是通过交叉表来关联的,不在一个表里,所以代码生成器没有生成,需要手动添加到生成的实体类里。再比如说你要把业务实体进行Select操作后返回的DataSet进行一些处理的话可以用 一下代码
public override void FinalizeData()
{
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
// perform finalization of data.
DataTable rawResults = internalData.Tables[0];
GWTrace.Trace( TraceLevel.Info, "Pre-Filtered Results rowcount : {0}", rawResults.Rows.Count);
DataRow[] filteredResults = rawResults.Select("ParentCategoryID NOT IN (" + catList + ")");
GWTrace.Trace( TraceLevel.Info, "Filtered Results Returns {0} Rows", filteredResults.Length);
foreach (DataRow delRow in filteredResults)
{
rawResults.Rows.Remove( delRow );
}
rawResults.AcceptChanges();
}
上面的代码是把指定的产品分类(catList)的产品从返回的DataSet里过滤掉的意思。catList是逗号分割开的字符串。
下面是业务层执行高级搜索的代码
string name,
string description,
string deptList,
decimal maxPrice,
decimal minPrice)
{
SqlPersistenceContainer spc = new SqlPersistenceContainer( CMPConfigurationHandler.ContainerMaps["AdvancedSearch"]);
AdvancedSearchSet advSet = new AdvancedSearchSet();
advSet.SKU = sku;
advSet.Description = description;
advSet.Name = name;
advSet.CategoryFilter = deptList;
advSet.MaxPrice = maxPrice;
advSet.MinPrice = minPrice;
spc.Select( advSet );
advSet.FinalizeData();
GWTrace.Trace( TraceLevel.Info, "After finalizedata, advSet.table0 rowcount {0}",
advSet.ResultSet.Tables[0].Rows.Count);
return advSet.ResultSet;
}
最后一个功能就是元数据管理工具,具体是这样的,用小工具打开一个元数据,然后可以以界面的形式修改这个容器元数据的【存储过程名】,【容器ID】【参数名称】【参数长度】【参数类型】【参数方向】,其中【参数类型】【参数方向】是由下拉列表选定,最后点击保存就更新了,因为手工改元数据的xml文件很容易写做的,如果把Nvarchar写成NVarchar咱们的架构就不工作了,这样有个小工具比较保险。
暂时我感觉就先有这些功能吧,谁有兴趣来完成这项工作,在这里回帖报名哦。大概需要以下一些技术
1、熟悉.NET对XML的操作
2、对SQLSERVER数据库的了解
3、桌面程序的开发经验
4、熟悉CMP架构
群里成员都自告奋勇点儿哦,哪个功能做不出来,大家可以拿出来讨论的。