Ibatis+MVC 3.0 开发手记
近期公司需要开发网吧区域促销活动业绩统计系统,系统数据来源基于万象网管数据库,借这个机会运用一下学习的Ibatis与MVC3.0。
网站ORM层采用Ibatis,展示采用MVC 3.0的Razor
Ibatis引入程序集:
IBatisNet.Common
IBatisNet.Common.Logging.Log4Net
IbatisNet.DataMapper
Log4net
网吧各分层如下:
对于二个数据库采用sqlmap_mps.config与sqlmap_wx2006DB.config不同的配置文件实现。下面是其中sqlmap_mps.config的配置文件:
1 <?xml version="1.0" encoding="utf-8" ?>
3 < settings >
4 < setting cacheModelsEnabled ="true" />
5 < setting useStatementNamespaces ="false" />
6 </ settings >
7 < providers resource ="providers.config" />
8 < database >
9 < provider name ="sqlServer2005" ></ provider >
10 <!-- <dataSource name="IBatisNet" connectionString="server=sql.develop.itour.com.cn,3433;database=tempdb;user id=ncc2008;password=ncc2008;connection reset=false;"/> -->
11 < dataSource name ="DBMPS" connectionString ="server=localhost;database=DBMPS;user id=sa;password=123;connection reset=false;" />
12 </ database >
13 < sqlMaps >
14 < sqlMap resource ="Po/Maps/User.xml" />
15 < sqlMap resource ="Po/Maps/Admin.xml" />
16 < sqlMap resource ="Po/Maps/Promotion.xml" />
17 < sqlMap resource ="Po/Maps/IncomeLog.xml" />
18 </ sqlMaps >
19 </ sqlMapConfig >
其中resource="Po/Maps/User.xml" /> 配置方式在根目录加载,方便修改。
embedded="${root}xmlname.xml,${assembly}" />配置方式文件将在程序集资源文件加载
url是通过绝对路径进行加载(不建议)
MapperUtil类 Ibatis的通用类,对Ibatis方法进行封装。
1 private ISqlMapper mySqlMapper = null;
3 public const String WX2006DB_MAPPER = " sqlmap_wx2006DB.config ";
4 private String ConnectionString = null;
5 public MapperUtil()
6 {
7 mySqlMapper = this.Instance(MPSDB_MAPPER);
8 this.ConnectionString = mySqlMapper.DataSource.ConnectionString;
9 }
10 public MapperUtil(String sqlMapName)
11 {
12 mySqlMapper = this.Instance(sqlMapName);
13 this.ConnectionString = mySqlMapper.DataSource.ConnectionString;
14 }
15 // double check
16 public ISqlMapper Instance( string sqlMapName)
17 {
18 if (mySqlMapper == null)
19 {
20 lock ( typeof(SqlMapper))
21 {
22 if (mySqlMapper == null)
23 {
24 InitMapper(sqlMapName);
25 }
26 }
27 }
28 return mySqlMapper;
29 }
30 protected void InitMapper(String sqlMapName)
31 {
32 DomSqlMapBuilder builder = new DomSqlMapBuilder();
33 mySqlMapper = builder.Configure(sqlMapName);
34 }
上面定义了MapperUtil默认构造函数创建sqlmap_mps.config ,为了阻止并发时多次创建DomSqlMapBuilder 采用Double Check确保每次只有一个实现。
MapperFactory类采用简单工厂模式:
1 /// <summary>
3 /// </summary>
4 public class MapperFactory
5 {
6 public static MapperUtil InstanceMps()
7 {
8 return new MapperUtil(MapperUtil.MPSDB_MAPPER);
9 }
10 public static MapperUtil InstanceWX2006DB()
11 {
12 return new MapperUtil(MapperUtil.WX2006DB_MAPPER);
13 }
14 }
其后在实现时直接调用相关的方法进行实例化:
如ComputerDao类:
2 {
3 MapperUtil mapper = MapperFactory.InstanceWX2006DB();
4 public IList<Computer> ShowAllComputer()
5 {
6 return mapper.ExecuteQueryForList<Computer>( " Computer.ShowAllComputer ", null) ;
7 }
8 public IList<Computer> ShowPagerComputer(Int32 offset,Int32 pagesize)
9 {
10 Hashtable ht = new Hashtable();
11 ht.Add( " offset ", offset);
12 ht.Add( " pagesize ", pagesize);
13 return mapper.ExecuteQueryForList<Computer>( " Computer.ShowPagerComputer ", ht);
14 }
15 }
在sqlMap映射文件中有一部分需要注意的:
一、Insert 添加后返回该新增行主键
1 <insert id="Admin.Insert" parameterClass="Admin">
3 < selectKey resultClass ="int" property ="Id" type ="post" >
4 <![CDATA[ SELECT @@IDENTITY AS Id ]]>
5 </ selectKey >
6 </ insert >
二、映射中的传入参数如果不是实体类可以通过Hashtable方式传入,分页就是最好的例子
2 SELECT TOP $pagesize$ sCom FROM ( SELECT ROW_NUMBER() OVER (ORDER BY t.sCom ) AS RowNumber,* FROM tStat AS t) A WHERE RowNumber > $pagesize$*($offset$-1)
3 </ select >
4 < parameterMaps >
5 < parameterMap id ="QueryConditionParameter" class ="HashTable" >
6 < parameter property ="pagesize" column ="pagesize" direction ="Input" />
7 < parameter property ="offset" column ="offset" direction ="Input" />
8 </ parameterMap >
9 </parameterMaps>
三、在遇到需要转义的符号时可以通过采用<![CDATA[]]>避免错误
如查找时的小于号处理方式:
2 <![CDATA[
3 SELECT SUM(cEffect) AS sum, sCom FROM tLogs WHERE dtTime2< '$endtime$' AND dtTime1 > '$starttime$' AND sCom='$pcNumber$' GROUP BY sCom
4 ]]>
5 </ select >
四、在映射SQL SERVER 里面的money(不被提倡)时可以采用Decimal来作为dbType
Service通过调用Dao并实现业务逻辑:
如 FormsAuthentication.SetAuthCookie(name,createPersistentCookie); 识别访问用户角色的信息也在此设置。
MVC3.0 可以通过自定义AuthorizeAttribute来识别访问网站的角色。这一点作得相对比较好,原来的WebForm的用户权限一般都定义BasePage继承 Page 然后重写 protected override void OnInit(EventArgs e) 进行设置。
因为项目Authorize已经足够,下面写的是大概的实现方式,多个角色,可以在AuthorizeCore实现。
1 public class AuthAttribute:AuthorizeAttribute
3 protected override bool AuthorizeCore(HttpContextBase httpContext)
4 {
5 if (httpContext == null)
6 throw new ArgumentNullException( " httpContext ");
7 if (!httpContext.User.Identity.IsAuthenticated)
8 return false;
9 if (httpContext.User.Identity.Name!= null)
10 return true;
11 return false;
12 }
13 }
Razor 方面在尝试使用遇到了不少学习中不到位的,也是常见到的问题:
1、一个cshtml页面在如果不需要母版的时候需要在页头加上:
@{
Layout = null;
}
2、需要在母版扩展一个区别写JavaScript与CSS
@RenderSection("Head",required:true)
这样每个页面可以通过在其页面加入
@section Head{
}
来添加内容。
3、JavaScript与CSS的引入采用
<script src="@Url.Content("~/Content/datetimepicker.js")" type="text/javascript"></script>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />