轉載:http://www.cnblogs.com/wellsoho/archive/2009/09/11/1564880.html
在自己學習NHibernate+MVC時,吃了不少苦,開發中也總結了些問題。發表出來,以便新學者能有所借鑒少走些彎路。
Nhibernate 要求model實體類對於lazy="true" ,字段屬性前需要加 virtual
sqlserver2005和oracle10g的hibernate.cfg.xml如何配置?
A:sqlserver2005配置如下
<!-- NHibernate sqlserver2005配置-->
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="db1">
<!-- properties -->
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="connection.connection_string">
Server=.;initial catalog=NhibernateTest;User Id=sa;Password=sa
</property>
<property name="use_outer_join">true</property>
<property name="use_proxy_validator">true</property>
<!--<property name="show_sql">false</property>-->
<!--<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>-->
<!-- mapping files -->
<mapping assembly="Kang.Model" />
</session-factory>
</hibernate-configuration>
Oracle10g配置如下:
<!-- NHibernate Oracle10g配置-->
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
<session-factory name="db1">
<!-- properties -->
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.OracleClientDriver<</property>
<property name="dialect">NHibernate.Dialect.Oracle9Dialect<</property>
<property name="connection.connection_string">
data source=KANGSHI;User ID=huobj;Password=huobj
</property>
<property name="use_outer_join">true</property>
<property name="use_proxy_validator">true</property>
<!--<property name="show_sql">false</property>-->
<!--<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>-->
<!-- mapping files -->
<mapping assembly="Kang.Model" />
</session-factory>
</hibernate-configuration>
Q:無法將類型為“NHibernate.Dialect.MsSqlCeDialect”的對象強制轉換為類型“NHibernate.Driver.IDriver”。
A:當切換數據庫時,相應的connection.driver_class屬性是需要調整
oracle10g是NHibernate.Driver.OracleClientDriver
MsSql2005是NHibernate.Driver.SqlClientDriver
Q:could not execute query
A:總的原則是,Nhibernate查詢還是遵守sql原規則的。
1 字段名稱不對,
2 字段格式不對,注意日期、數字和字符
3<property type="string" length="50" name="RoleName" column="[RoleName]" />
oracle必須把RoleName的[]去掉。而sqlsever去不用去[]都行。
Q:The type System.Int32 can not be assigned to a property of type System.String setter of Kang.Model.Entities.USR_UserInfo.LoginID
A: 主鍵LoginID原定義的是int ,應該改成string
Q:Invalid Cast (check your mapping for property type mismatches); setter of Kang.Model.Entities.USR_UserInfo
A:length="80" 必須小於數據庫表中字段的長度。另外,就是實體類中屬性類的類型要和nhibernate-mapping 中的type同。
Q:數據庫中的Date、DateTime和TimeStamp類型區別?
A:
DATETIME, DATE和TIMESTAMP類型是相關的。本文描述他們的特征,他們是如何類似的而又不同的。
DATETIME類型用在你需要同時包含日期和時間信息的值時。MySQL檢索並且以'YYYY-MM-DD HH:MM:SS'格式顯示DATETIME值,支持的范圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。(“支持”意味着盡管更早的值可能工作,但不能保證他們可以。)
DATE類型用在你僅需要日期值時,沒有時間部分。MySQL檢索並且以'YYYY-MM-DD'格式顯示DATE值,支持的范圍是'1000-01-01'到'9999-12-31'。
TIMESTAMP列類型提供一種類型,你可以使用它自動地用當前的日期和時間標記INSERT或UPDATE的操作。如果你有多個TIMESTAMP列,只有第一個自動更新。
SqlDateTime 溢出。必須介於 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM 之間。
滴答數必須介於 DateTime.MinValue.Ticks 和 DateTime.MaxValue.Ticks 之間。
參數名: ticks
A:實體類中這樣定義就ok了 private DateTime _CreateDate = new DateTime(2009 - 9 - 9);
Q:有的哥們這么寫,但是問題是麻煩。
var whitelist = new[] { "UserId", "UserName", "UserParssord", "UserMail" };
UpdateModel(user, whitelist);
uService.UpdateUserInfo(user);
return RedirectToAction("Index");
A: 可以這樣寫
model = bll.GetModel(id);
UpdateModel(model);
bll.UpdateData(model);
return RedirectToAction("Index")
父子表關聯映射 ==============================================
Q: 用戶代碼未處理 NHibernate.PropertyAccessException
Message="Invalid Cast (check your mapping for property type mismatches); setter of Kang.Model.Entities.USR_UserInfo"
Source="Kang.NHibernateHelper"
A:<!--多對一關系:Users屬於一個Role-->
<many-to-one name="RoleID" column="RoleID" not-null="true" class="Kang.Model.Entities.RoleInfo" foreign-key="FK_RoleUsers" />
<!--一對多關系:Role有一個或多個Users-->
<set name="Users" table="`USR_UserInfo`" generic="true" inverse="true">
<key column="RoleInfo" foreign-key="FK_RoleUsers"/>
<one-to-many class="Kang.Model.Entities.USR_UserInfo"/>
</set>
Q:Duplicate property mapping of RoleID found in Kang.Model.Entities.USR_UserInfo
A:有重復的屬性定義。屬性對象化,頁面調用顯示時可以再調用屬性的屬性,如:model.RoleID.RoleName
Q:Could not initialize proxy - the owning Session is disconnected
A:對於父子關聯表,把lazy="false"
(1)、Nhibernate錯誤”No persister for ”
Nhibernate錯誤”No persister for <entity name>”
例如:”No persister for DomainModel.Entities.User”
1.檢查hibernate.cfg.xml是否配置mapping 如:<mapping assembly="”DomainModel”/">
2.檢查User.hbm.xml文件屬性“生成操作”的值,從“內容”修改為“嵌入的資源”
(2)、Could not find the dialect in the configuration這個錯誤,
這是數據庫配置問題
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
換成
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
(3)、The ProxyFactoryFactory was not configured 報錯
因為沒有引用上面那個配置中的工廠類所以在引用下 Required_For_LazyLoading文件夾下的 LinFu下的NHibernate.ByteCode.LinFu.dll 當然也可以用 Castle 那要改下配置</hibernate-mapping></hibernate-mapping></mapping></entity>
(4)、Could not compile the mapping document
解決辦法:
調試查看到InnerText為,不應該為<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">,然后我把改為
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">后,此問題解決.
(5)、NHibernate.InvalidProxyTypeException
The following types may not be used as proxies: TestCleanSnow.BjkptOaxtCleanupsnow: method set_IsDeleted should be virtual TestCleanSnow.BjkptOaxtCleanupsnow: method set_IsChanged should be virtual TestCleanSnow.BjkptOaxtCleanupsnow: method Clone should be virtual TestCleanSnow.BjkptOaxtCleanupsnow: method get_IsChanged should be virtual TestCleanSnow.BjkptOaxtCleanupsnow: method get_IsDeleted should be virtual
解決辦法: 在XML的 <class name="TestCleanSnow.BjkptOaxtCleanupsnow,TestCleanSnow" table="B_JKPT_OAXT_CLEANUPSNOW"> 添加 lazy="false" .
(6)、在執行 session.Save(cs);
時,出現could not get next sequence value[SQL: SQL not available] Nhibernate
解決辦法:
把相應XML的
<generator class="native" /> 改為 <generator class="assigned" />
以上我做Oracle時出現的錯誤,操作sqlserver的時候應該為 <generator class="native" />.
(7)、轉載與: http://hi.baidu.com/zsea/blog/item/7d999e3d8a54c203baa1678d.html
一、Test.Model.Person.hbm.xml(2,2): XML validation error: 未能找到元素“urn:nhibernate-mapping-2.0:hibernate-mapping”的架構信息。
將2.0改為2.2
二、 The following types may not be used as proxies:
Test.Model.Person: method set_Id should be virtual
Test.Model.Person: method get_Name should be virtual
Test.Model.Person: method set_Name should be virtual
Test.Model.Person: method get_Id should be virtual
類配置文件中Class的Lazy改為false
網上搜到的三種解決方案:
1. You can follow the advice of the exception and add "virtual" to all of your properties, and make sure your class is non-sealed. Obviously you'll want to do this if you think you might want to take advantage of the lazy-initializing proxy feature. However, changing your classes may not be practical or advisable if you have a legacy codebase, or it may just bother you that a "transparent" persistence framework is dictating how you design certain aspects of your value classes. That's where Options 2 and 3 come in. Both of those involve changing back to the old behavior.
name="NorthwindClasses.Category, NorthwindClasses"
table="Categories"
lazy ="false"
>
面向對象的數據庫開發框架NHibernate
近年來,越來越多的人認識到使用面向對象的企業應用開發框架來進行系統的開發有着諸多的好處。在項目設計階段,使用UML建模語言設計業務域對象模型,從模型出發,定義業務域對象,運行時對業務域對象的屬性進行操作,直接將業務域對象保存到數據庫,或者從數據庫加載,消除對面向數據集的Sql的依賴,這就是通常所說的OR Mapping,對象-關系映射方法。
在Java平台上,OR Mapping的開源框架的No.1就是Hibernate,Hibernate是一個輕量級的OR Mapping解決方案,一經推出就取得了巨大的成功,在剛剛發布的EJB3.0的草案中就吸收了大量的Hibernate中的特性。從2004年三月開始,SourceForge上發布了.Net版本的NHibernate的Alpha版本,目前NHibernate的開發進展非常順利,平均每一個半月就會發布一個新的版本。
NHibernate具有以下特性:
對象持續性:能夠管理.Net類到數據庫表的映射,以對象的方式存取數據,支持復雜對象、復合對象,支持對象之間的關聯,比如繼承,聚合,關聯。OR Mapping的定義都是基於XML,具有很好的擴展性和通用性。可以支持現有的數據庫定義,很好地保護用戶投資。
支持對象查詢:提供了面向對象的查詢語言(HQL和條件查詢),可以根據條件查詢復合對象以及對象集合。
支持事務:創建還必須支持悲觀鎖的事務,並提供了樂觀鎖的並發支持。
性能優化:允許用戶使用定制的Sql來提高查詢的性能,提供了多種SQL自動策略開關,使得框架生成的Sql語句具有非常優化的性能。提供了靈活的Cache緩沖機制,以及延遲加載,批量更新的策略,保證一般應用的性能不會低於相應的數據集應用。
數據庫平台無關性:使用OR Mapping技術實現了數據庫平台無關性,可以隨時切換開發及數據庫發布平台,方便移植。
NHibernate的體系結構示意圖:
圖中的Session對應於應用程序同持久層的一次對話,其中保存有必需的持久化對象的緩存,可以通過標識符查找持久對象。持久層同底層數據庫之間的操作是通過ADO.Net來實現的。
包的介紹:
NHibernate.dll是核心的程序集
Log4net.dll是日志記錄程序集
Iesi.Collections.dll是集合框架的程序集
Castle.DynameicProxy.dll控制反轉的程序集
編碼步驟:
第一步:Web.Config/App.Config
第二步: 實體類
第三步:創建使用NHibernate的配置文件
freetextbox是一款免費的asp.net網頁編輯器,官方默認為英文版,可以設置文字樣式、在線排版、圖片上傳等。
是一款非常好用,功能很強大的在線編輯器,尤其是能真正實現圖片上傳,目前網上流傳的幫助都是針對老版本的,所以為大家整理一個針對新版本的幫助,希望對大家有用:
目錄結構:
aspnet_client freetextbox的外觀文件,直接拷貝到你的工程的目錄下就可以了。
docs 幫助文檔
examples 官方例子,包括了各類應用的演示和實現過程,包括:功能設置、下拉顯示、多語言(包括簡體中文、繁體、英文等)切換、js調用、webparts應用、ajax無刷新交互等例子。
framework-2.0 適合.net freameork2.0使用的dll
framework-1.0 適合.net freameork1.1使用的dll
framework-1.0 適合.net freameork1.0使用的dll
使用方法:
1 在web應用程序中添加引用freetextbox.dll,自動添加到bin 目錄;
文件夾下有asp.net1.1/2.0/3.5各個環境下可以使用的freetextbox.dll;
添加引用時要根據使用的framework版本來引用相應的dll。
2 把aspnet_client下的freetextbox文件夾及其所有內容都拷貝到web項目中
3 在應用程序目錄下建立images目錄,此目錄用做上傳圖片的圖片庫,上傳的圖片都保持在該文件夾下
4 在aspx中使用:
頁頭添加
xml/html代碼
- <%@ register tagprefix="ftb" namespace="freetextboxcontrols" assembly="freetextbox" %>
引入 控件 標簽
添加<ftb:freetextbox>到 頁面 中需要的位置。
xml/html代碼
- <ftb:freetextbox id="freetextbox1" onsaveclick="savebutton_click" language="zh-cn"
- toolbarlayout="paragraphmenu,fontfacesmenu,fontsizesmenu,fontforecolorsmenu,fontforecolorpicker,fontbackcolorsmenu,fontbackcolorpicker|bold,italic,underline,strikethrough,superscript,subscript,removeformat|justifyleft,justifyright,justifycenter,justifyfull;bulletedlist,numberedlist,indent,outdent;createlink,unlink,insertimage|cut,copy,paste,delete;undo,redo,print,save|symbolsmenu,stylesmenu,inserthtmlmenu|insertrule,insertdate,inserttime|inserttable,edittable;inserttablerowafter,inserttablerowbefore,deletetablerow;inserttablecolumnafter,inserttablecolumnbefore,deletetablecolumn|insertform,inserttextbox,inserttextarea,insertradiobutton,insertcheckbox,insertdropdownlist,insertbutton|insertdiv,editstyle,insertimagefromgallery,preview,selectall,wordclean,netspell" runat="server" designmodecss="designmode.css"/>
-
- <asp:button id="savebutton" text="save" onclick="savebutton_click" runat="server" />
-
常用屬性:
language="zh-cn" 把顯示語言改為中文,默認為英文
toolbarlayout: 說明在線編輯器提供的相應功能
text: 提供默認值
toolbarstyleconfiguration:換膚,取值包括notset office2000 officexp officemac office2003
注意提交按鈕和freetextbox的onclick事件使用同一個處理方法
5 如果要實現上傳圖片功能 ,必須把ftb.imagegallery.aspx文件,拷貝到使用該控件的aspx文件相同的文件夾下。
6 獲取或者設置值: freetextbox1.text
this.freetextbox1.htmlstrippedtext 這個是將html標記去掉的文本
7 使用的頁面中需要設置 validaterequest="false"
否則會報錯:從客戶端.....中檢測到有潛在危險的 request.form 值。說明: 請求 驗證 過程檢測到有潛在危險的客戶端輸入值,對請求的處理已經中止。該值可能指示危及應用 程序安全的嘗試,如跨站點的腳本攻擊。通過在 page 指令或配置節中設置 validaterequest=false 可以禁用請求驗證
解決 辦法:
web.config中<system.web>下添加一個配置
頁面配置中添加validaterequest="false",即<%@ page ...... validaterequest="false"%>
下載 地址 :
http://freetextbox.com/
http://freetextbox.com/download/
首先介紹一下CKeditor的技術,其實CKeditor就是FCKeditor的升級版本,改名主要是與它公司的名字有關,這就是新出的版本Ckeditor3.0 官方網為:http://www.fckeditor.net/
develops Guide 這個開發指南相當不錯,一般我們學一樣東西都是直接去看這個技術的開發指南,里面有一般的用法,讓你迅速上手,而且很容易搞懂這些配置。首先下載FCKeditor2.6.5.zip包,這個包是必須的,而且與語言無關。第二個必須包是FCKeditor.net_2.6.3.zip包。下載完這兩個包,馬上就可以開始web開發了。
當然首先你要看看Demo的東西,畢竟它是官方自帶的例子,肯定值得我們去研究,而且里面的代碼很有參考價值,到了這一步,我相信就很容易做了。
開發指南網址:http://docs.cksource.com/CKEditor_3.x/Developers_Guide
下面講講FCKeditor.Net編輯器在.net環境的配置方法。
第一步:解壓縮FCKeditor_2.6.3.zip文件,並將解壓縮得到的fckeditor文件夾復制到你想使用這個編輯器的網站的根目錄下面。
第二步:把下載的FCKeditor.Net.zip隨便解壓縮到你硬盤的一個空目錄,里面是FCKeditor.Net的源代碼,可以對它進行再度開發,我這里講直接應用,我們要使用到是其目錄下的\bin\Debug目錄中的FredCK.FCKeditorV2.dll文件。在你的網站里面把這個FredCK.FCKeditorV2.dll添加到bin目錄下。
第三步:進入FCKeditor文件夾,編輯 fckconfig.js 文件,如下:
1、指定編輯器應用的編程環境,修改
var _FileBrowserLanguage = 'asp' ; // asp | aspx | cfm | lasso | perl | php | py
var _QuickUploadLanguage = 'asp' ; // asp | aspx | cfm | lasso | php
改為
var _FileBrowserLanguage = 'aspx' ; // asp | aspx | cfm | lasso | perl | php | py
var _QuickUploadLanguage = 'aspx' ; // asp | aspx | cfm | lasso | php
2、配置語言包。有英文、繁體中文等,這里我們使用簡體中文。
修改
FCKConfig.DefaultLanguage = 'en' ;
為
FCKConfig.DefaultLanguage = 'zh-cn' ;
3、配置皮膚。有default、office2003、silver風格等,這里我們可以使用默認。
FCKConfig.SkinPath = FCKConfig.BasePath + 'skins/default/' ;
4、在編輯器域內可以使用Tab鍵。(1為是,0為否)
FCKConfig.TabSpaces = 0 ; 改為FCKConfig.TabSpaces = 1 ;
5、加上幾種我們常用的字體的方法,例如:
修改
FCKConfig.FontNames = 'Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;
為
FCKConfig.FontNames = '宋體;黑體;隸書;楷體_GB2312;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana'
6、編輯器域內默認的顯示字體為12px,想要修改可以通過修改樣式表來達到要求,打開/editor/css/fck_editorarea.css,修改font-size屬性即可。如font-size: 14px;
7、關於安全性。
如果你的編輯器用在網站前台的話,那就不得不考慮安全了,在前台千萬不要使用Default的toolbar,要么自定義一下功能,要么就用系統已經定義好的Basic,也就是基本的toolbar,
修改
FCKConfig.ToolbarSets["Basic"] = [
['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About']
為
FCKConfig.ToolbarSets["Basic"] = [
['Bold','Italic','-','OrderedList','UnorderedList','-','Unlink','-','Style','FontSize','TextColor','BGColor','-','Smiley','SpecialChar','Replace','Preview']
] ;
第四步:在Web.Config文件里面添加,如下所示
1、配置WebConfig,在<appSettings>節點添加,如下所示:
如果你用的是默認的上傳功能,則
<add key="FCKeditor:BasePath" value="~/fckeditor/"/>
<add key="FCKeditor:UserFilesPath" value="/網站名稱/UploadFiles/"/>
第五步:在頁面里應用FCKeditor編輯器
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" validateRequest="false" %>
<%@ Register Assembly="FredCK.FCKeditorV2" Namespace="FredCK.FCKeditorV2" TagPrefix="FCKeditorV2" %>
// 這里要主要兩個參數
// 默認為<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
// 我們要添加一個參數 validateRequest=false,否則提交帶html代碼的內容會報錯
// 從客戶端(...)中檢測到有潛在危險的 Request.Form 值。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>無標題頁</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<FCKeditorV2:FCKeditor ID="FCKeditor1" runat="server">
</FCKeditorV2:FCKeditor>
</div>
</form>
</body>
</html>
如何獲取其內容呢?讀取FCKeditor1控件的Value屬性值即可。
到這里基本OK了,但是我發現在使用圖片上傳功能的時候,會彈出一個阻止框,顯示"this connector is disabled Please check the"editor/filemanager/connectors/aspx/config.aspx",解決這個錯誤的方法是打開editor/filemanager/connectors/aspx/config.ascx修改CheckAuthentication()方法,返回true
C# code
private bool CheckAuthentication()
{
// WARNING : DO NOT simply return "true". By doing so, you are allowing
// "anyone" to upload and list the files in your server. You must implement
// some kind of session validation here. Even something very simple as...
//
// return ( Session[ "IsAuthorized" ] != null && (bool)Session[ "IsAuthorized" ] == true );
//
// ... where Session[ "IsAuthorized" ] is set to "true" as soon as the
// user logs in your system.
return true;
}
下載地址:http://www.fckeditor.net/download
FCKeditor使用
一、配置
1、在www.fckeditor.net點擊Download,下載FCKEditor_2.5.1.zip和FCKEditor.Net(ASP.NET Control to easily integrate FCKEditor on .Net Web pages.)
2、新建一項目,比如叫FCK。解壓FCKEditor_2.5.1.zip,里面有個fckeditor目錄。把該目錄整個復制到新建的ASP.NET項目根目錄下。打開fckeditor目錄下的fckconfig.js,修改二項:
FCKConfig.DefaultLanguage = 'en' ;
改為
FCKConfig.DefaultLanguage = 'zh-cn' ;
-----------------------------------------------------
var _FileBrowserLanguage = 'php' ; // asp | aspx | cfm | lasso | perl | php | py
var _QuickUploadLanguage = 'php' ; // asp | aspx | cfm | lasso | perl | php | py
改為
var _FileBrowserLanguage = 'aspx' ; // asp | aspx | cfm | lasso | perl | php | py
var _QuickUploadLanguage = 'aspx' ; // asp | aspx | cfm | lasso | perl | php | py
3、在vs05/08的工具箱上新建一個名叫FCKEditor的Tab,然后在里面點右鍵,選擇Choose Item,定位到解壓FCKEditor.Net后生成的FCKEditor2.51\FCKeditor.Net_2.5\bin\Release\2.0目錄下的FredCK.FCKEditorV2.dll。該Tab下就會生成一個FCKEditor的.net組件。在vs的Design模式下把該組件拖放到界面上。點擊該組件,在屬性面板上設置BashPath為/FCK/fckeditor/,注意這里的FCK就是你建的ASP.NET的項目名稱,fckeditor為項目根目錄下的目錄名稱。(注意:/FCK/fckeditor/前后的斜杠,少了一個都不會顯示編輯器的)。Ctrl+F5!
其它次要配置(不影響使用):
* 可以把fckeditor目錄及其子目錄下所有下划下開頭的范例、源文件刪掉。
* 可以在fckeditor目錄下只保留fckconfig.js、fckeditor.js和幾個xml文件,其余全部刪掉。
* fckeditor目錄下的editor目錄下有個filemanager目錄,把該目錄下的borswer\default\connectors目錄中除aspx目錄以外的全部目錄刪掉。
* 可以把editor\lang目錄下除zh-cn.js、en.js、zh.js之外的全部刪掉。
二、圖片上傳
FCKEditor支持圖片上傳。可以在ASP.NET項目根目錄下添加一目錄,起名為UploadFiles.
在web.config里的appSettings段里
<appSettings>
<add key="FCKEditor:BasePath" value="/FCK/fckeditor"/>
<add key="FCKeditor:UserFilesPath" value="/FCK/UploadFiles/" />
</appSettings>
注意UserFielsPath,這里設置的/FCK/UploadFiles/指定了要上傳的目錄。個人認為這里的FCK可以認為是服務器上的虛擬目錄名。(另外發現如設為時不起作用)。
當上傳圖片時有可能遇到"this connector is disabled Please check the"editor/filemanager/connectors/aspx/config.aspx"的錯誤,這時可以更改fckeditor\editor\filemanager\connectors\aspx\config.ascx的CheckAuthentication()方法,返回true.
三、簡單的FCKEditor存取數據庫及顯示
1、在項目里添加新項Sql Server Database, 文件名保留為Database.mdf。在里面新建一表MyTable,只有兩個字段,一個int型自動增加的primary key, 另一個是text類型的MyContent. 我們要把FCKEditor1.Value值存到這個字段里。
2、先做個顯示的頁面。項目增加一個Show.aspx,拖一個SqlDataSource,設置一下返回MyTable的內容。再用Repeater顯示。
//代碼
<asp:Repeater ID="myRepeater" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<%# Eval("MyContent") %>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%nbsp;ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [OID], [MyContent] FROM [MyTable] ORDER BY [OID] DESC"></asp:SqlDataSource>
3、存入數據庫
項目中引用System.Configuration(為了使用System.Web.WebConfigurationManager)
在FCKEditor界面上入一個按鈕,然后
protected void Button1_Click(object sender, EventArgs e)
{
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "insert into MyTable(MyContent) values(@FCKContent)";
cmd.Parameters.AddWithValue("FCKContent",FCKeditor1.Value);
conn.Open();
cmd.ExecuteNonQuery();
}
}
前言:
與ASP相比ASP.NET在Web應用開發上無疑更容易,更有效率。Web開發大部分還是圍繞着數據操作,建立數據庫存儲數據,編寫代碼訪問和修改數據,設計界面采集和呈現數據。走過Asp.net學習入門階段后,真正開始着手開發一個Web項目時,才發現錯綜復雜的數據與關聯根本就不是SqlDataSource和AccessDataSource數據源控件能簡單解決的,而恰恰是被忽視了的一個ObjectDataSource數據源控件才是真正踏入開發門檻的關鍵,由此也對三層架構模式有了初步體驗。
一.ASP.NET三層架構介紹
設計模式中的分層架構(可以參考一下J2EE中MVC模式)實現了各司其職,互不干涉,所以如果一旦哪一層的需求發生了變化,就只需要更改相應的層中的代碼而不會影響到其它層中的代碼。這樣就能更好的實現開發中的分工,有利於組件的重用。所以這些年關於模式的研究有很多成果,應用也很廣泛。一個好的模式在程序開發和后期維護中作用重大。
ASP.NET三層架構自底向上分為:數據訪問層(DAL),業務邏輯層(BLL)和表示層(PL)。
數據訪問層(DAL):使用了一個強類型的DataSet作為數據訪問層,只是單純的對數據進行增,刪,改,查詢和判斷存在等等較通用的數據訪問方法(由SQL語句來提供),不應該有“事務”存在。
業務邏輯層(BLL):業務邏輯層是在數據訪問層和表示層之間進行數據交換的橋梁,按業務需求調用數據訪問層中的方法組合,集合了各種業務規則到一個BLL中,例如通過條件進行判斷的數據操作或“事務”處理。BLL都是以類庫(Class Library)的形式來實現的。
表示層(PL):表示層是為客戶提供用於交互的應用服務圖形界面,幫助用戶理解和高效地定位應用服務,呈現業務邏輯層中傳遞的數據,用ASP.NET頁面來實現。
二.三層架構應用實現
隨着ASP.NET 的不斷升級,可以很方便的使用ASP.NET 來構建B/S 三層架構的應用程序,下面以“教師業務信息管理系統”項目中的部分例子來演示如何使用ASP.NET 2.0 和SQL Server 2005數據庫來構建一個三層架構的應用程序。
1.創建數據庫
打開SQL Server 2005,新建一個數據庫“TeacherDb”,建立如下所示結構的兩個表“PersonInfo”和“JobInfo”。兩表以PersonIDNumber作為關聯字段,存儲18位身份證號碼。
2.創建數據訪問層
在開始創建數據訪問層(DAL)之前,首先需要創建一個網站,配置好數據庫鏈接。
第一步:創建一個Web項目,配置數據庫連接
打開Visual Studio 2005(以下簡稱VS2005)集成開發環境, 首先創建一個C#語言的ASP.NET網站,並將其命名為WebSite,設置位置(Location)列表的選項為文件系統( File System),然后選這一個放置這個網站的文件夾,然后選擇編程語言為C#。Visual Studio會為你生成一個新的網站,同時生成一個名為Default.aspx的網頁,和一個App_Data文件夾。
第二步:創建數據訪問層,配置數據庫連接
接下來創建數據訪問層,添加一個強類型的DataSet。在解決方案管理器里的項目節點上按右鼠標,選擇“添加新項”,在模板列單里選擇“數據集”,將其命名為DataSet1.xsd。接下來會出現“TableAdpater”配置向導的窗口,選擇數據庫服務器,設置好各項參數,並按照提示逐步完成。需要注意:
1.指定連接的數據庫字符串,並選擇將連接字符串保存到web.config文件中去。
2.命令類型選擇“使用SQL語句”,通過“高級選項”選擇“生成Insert、Update和Delete語句”,通過“查詢生成器”生成要裝載數據的“Select語句”。並為方法命名。
SELECT ID, UserID, TrueName, PersonIDNumber, Sex, BirthDate, Nation, NativePlace,
Polity, JoinPolityTime, PersonImageUrl, Telephone, MobiePhone, Email
FROM EM_P_PersonInfo
針對項目需求對數據庫中各表查詢操作分別建立各種方法,完成后的可能如下圖。
跟底層數據源相關的所有編碼,比如建立到數據庫的連接,發出SELECT,INSERT ,UPDATE和DELETE命令等的編碼,都應該放置在DAL中。表現層不應該包含對這些數據訪問編碼的任何引用,而應該調用DAL中的編碼處理所有的數據訪問請求。數據訪問層包含訪問底層數據庫數據的方法。至此,清晰構建出數據訪問層,之后可在“業務邏輯層”和“表示層”通過調用自動生成的TableAdpater及相關類來操作數據。由於“數據集”是強類型,對於數據庫中的NULL數據需要使用方法來判斷,這些內容在后續內容中再詳細描述。
3.創建業務邏輯層
數據訪問層(DAL)將數據訪問的細節從表示層中分離出來了,可它卻不能處理任何的業務規則。比如判斷數據的有效性。這些工作將由業務邏輯層(簡稱BLL)來承擔,在以下應用程序中,將BLL實現為App_Code文件夾中的一系列的類。每一個BLL類都對應DAL中的一個TableAdapter,它們都從各自的TableAdapter中得到讀取、插入、修改以及刪除等方法以應用合適的業務規則。
第一步:創建BLL類
在App_Code文件夾中創建2個類文件。在解決方案瀏覽器(Solution Explorer)中右鍵點擊App_Code文件夾,並選擇新建項目(New Item),然后在彈出的對話框中選擇“類”模板(Class template)就可以創建新的類文件了。將這2個文件分別命名為UserBLL以及JobBLL。
第二步:通過BLL類訪問類型化數據集
為UserBLL和JobBLL類分別添加如下方法:
(1) UserBLL.css
l updateUser(string UserName, String PersonIDNumber, int SchoolID, string Password, string Sex, string TrueName, bool InPosition)
l updateUser(String PersonIDNumber, string TrueName, string BirthDate, string Nation, string NativePlace, string Polity, string JoinPolityTime, string Telephone, string MobiePhone, string Email)
l getPersons(int SchoolID,string TrueName)
l getPersonByPID(string PersonIDNumber)
l deleteUser(string UserName, String PersonIDNumber, int? SchoolID)
l addUser(string UserName, String PersonIDNumber, int SchoolID, string Password, string Sex, string TrueName, bool InPosition)
(2)JobBLL.css
l getPersonJob(string PersonIDNumber)
l updateUser(String PersonIDNumber, string Post1, string Post2, string JoinTime, int? CountryWorkedTime, string MasteSubject, string SecondSubject, string SchoolPhase, int? MotherClassTime)
以下為JobBLL.css的代碼(UserBLL.css的代碼太長,不列出)
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using TeacherTableAdapters;
/// <summary>
/// JobBLL 的摘要說明
/// </summary>
[System.ComponentModel.DataObject]
public class JobBLL
{
private JobInfoTableAdapter _JobAdapter = null;
public JobBLL()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
protected JobInfoTableAdapter Adapter
{
get
{
if (_JobAdapter == null)
_JobAdapter = new JobInfoTableAdapter();
return _JobAdapter;
}
}
//select
[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
public Teacher.JobInfoDataTable getPersonJob(string PersonIDNumber)
{
return Adapter.GetPersonJobByPID(PersonIDNumber);
}
//update
[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, false)]
public bool updateUser(String PersonIDNumber, string Post1, string Post2, string JoinTime, int? CountryWorkedTime, string MasteSubject, string SecondSubject, string SchoolPhase, int? MotherClassTime)
{
if (string.IsNullOrEmpty(PersonIDNumber))
{
return false;
}
try
{
Teacher.JobInfoDataTable PersonJob = Adapter.GetPersonJobByPID(PersonIDNumber);
Teacher.JobInfoRow PersonJobPID;
if (PersonJob.Count == 1)
{
PersonJobPID = PersonJob[0];
}
else
{
return false;
}
if (!string.IsNullOrEmpty(Post1))
{
PersonJobPID.Post1 = Post1;
}
else
{
PersonJobPID.SetPost1Null();
}
if (!string.IsNullOrEmpty(Post2))
{
PersonJobPID.Post2 = Post2;
}
else
{
PersonJobPID.SetPost2Null();
}
if (!string.IsNullOrEmpty(MasteSubject))
{
PersonJobPID.MasteSubject = MasteSubject;
}
else
{
PersonJobPID.SetMasteSubjectNull();
}
if (!string.IsNullOrEmpty(SecondSubject))
{
PersonJobPID.SecondSubject = SecondSubject;
}
else
{
PersonJobPID.SetSecondSubjectNull();
}
if (!string.IsNullOrEmpty(SchoolPhase))
{
PersonJobPID.SchoolPhase = SchoolPhase;
}
else
{
PersonJobPID.SetSchoolPhaseNull();
}
if (!(CountryWorkedTime == null))
{
PersonJobPID.CountryWorkedTime = CountryWorkedTime.Value;
}
else
{
PersonJobPID.SetCountryWorkedTimeNull();
}
if (!(MotherClassTime == null))
{
PersonJobPID.MotherClassTime = MotherClassTime.Value;
}
else
{
PersonJobPID.SetMotherClassTimeNull();
}
if (!string.IsNullOrEmpty(JoinTime))
{
PersonJobPID.JoinTime = DateTime.Parse(JoinTime);
}
else
{
PersonJobPID.SetJoinTimeNull();
}
int rowAffect1 = Adapter.Update(PersonJobPID);
return (rowAffect1 == 1);
}
catch (System.Configuration.Provider.ProviderException e)
{
return false;
}
}
}
說明:
(1)using TeacherTableAdapters; 引用DAL層命名空間,自動生成,必須。否則無法使用類。
(2)JobInfoTableAdapter類,對應DAL中的TableAdapter適配器JobInfo,通過這個類來調用增、刪及改等數據操作。
(3)使用JobInfoDataTable PersonJob來裝載查詢返回的數據,是DataSet中的強類型數據表,結構和數據類型由數據庫定義。使用JobInfoRow PersonJobPID來載入表中的某一行。行字段訪問用如下形式:Row變量.字段名(如PersonJobPID.Post1)。
Teacher.JobInfoDataTable PersonJob = Adapter.GetPersonJobByPID(PersonIDNumber);
Teacher.JobInfoRow PersonJobPID = PersonJob[0];
(4)數據庫中某些表字段在設計時可能被允許空值(null),強類型DataTable中對字段的判空與賦空值不能采用以下形式:
l !string.IsNullOrEmpty(PersonJobPID.Post1)
l PersonJobPID.Post1 == null;
l PersonJobPID.Post1 = null;
正確的做法是采用行類型變量(Teacher.JobInfoRow PersonJobPID)為每個字段生成的“空值方法”操作:
l void PersonJobPID.SetPost1Null();
l bool PersonJobPID.IsPost1Null()
(5)JobInfoDataTable或JobInfoRow中數據存儲在內存中,修改后的數據要反映到數據庫中采用適配器方法Update().
int rowAffect1 = Adapter.Update(PersonJobPID);
至此業務邏輯層構建完成。
4.表示層-使用ObjectDataSource展現數據
在完成應用程序架構后,我們可以實現多種報表展現。ASP.NET 2.0的數據源控件提供了一種新的方式,使用這些控件可以輕松的從創建的業務邏輯層中進行數據綁定,甚至不需要手寫一行的代碼。
ASP.NET 2.0提供了五種內置的數據源控件:SqlDataSource、AccessDataSource,、ObjectDataSource、XmlDataSource、和SiteMapDataSource。基於已有的業務邏輯類我們將使用ObjectDataSource。
ObjectDataSource充當別的對象的代理。通過配置ObjectDataSource,我們指定這些底層的對象,還有這些對象的方法如何映射到ObjectDataSource的Select、Insert、Update和Delete方法。一旦底層的對象被指定並且其方法映射到ObjectDataSource的方法后,我們就可以把ObjectDataSource綁定到頁面上的Data Web服務器控件。ASP.NET提供了許多Data Web 服務器控件,包括GridView、DetailsView、RadioButtonList和DropDownList等等。在頁面的生命周期中,Data Web 服務器控件可能需要訪問它所綁定的數據,這將通過調用ObjectDataSource的Select方法來實現;如果這個Data Web 服務器控件還支持插入、更新或者刪除,那么將調用ObjectDataSource的Insert、Update或者Delete方法。這些調用會通過ObjectDataSource被發送到適當的底層對象的方法。
第一步:添加和配置ObjectDataSource控件
(1)新建一個“Web窗體”模板文件(UserView.aspx),語言Visual C#,選擇“將代碼發在單獨文件中”。
(2)拖入一個“GirdView”控件,點擊智能標記中的“配置數據源”,選擇“新建數據源…”,進入數據源配置向導來添加一個ObjectDataSource。
(3)進入數據源配置向導。首先給ObjectDataSource指定一個業務對象。如果勾選上“只顯示數據組件”,那么下拉框中就僅僅顯示出那些以[DataObject]特征修飾過的對象。可以不勾選“只顯示數據組件”從而看見所有對象。從下拉列表中選擇業務對象UserBLL 。
根據頁面設計的需要為SELECT,UPDATE,INSERT及DELETE操作指定相應的業務對象的方法。這些方法已經在業務邏輯層中定義。如果用GridView及DetailsView服務器控件呈現數據,SELECT操作是必須的。
第二步:配置GridView
從GridView的智能標記點選“編輯列”,為“選定的字段”指定標題名,格式,刪除不需要的列,添加命令字段(Command Field)等。操作比較繁瑣,看參考相關資料。完成后的樣子類似下圖:
根據設計需求將頁面設計完成。至此,表示層的搭建過程簡單演示一下。
三.總結
用了幾天時間將前段時間的學習和項目開發中的框架構建簡單做了個總結,這不是一個教程類的文章,許多細節性的東西不可能面面俱到。程序開發是一件比較辛苦的事,過程可能很枯燥,不過對此感興趣的人會在不斷學習中體會到其中的樂趣。
- 23:13
- 評論 / 瀏覽 (0 / 2325)
基於UML和ASP.NET實現三層B/S結構系統開發
作者:胡穎輝 寧賽飛 來源:IBM
摘 要 進行良好的系統分析和設計是軟件項目開發的關鍵,構架設計的合理與否往往決定了項目的成敗。本文結合一個項目的開發,闡述了基於UML的系統建模過程和基於ASP.NET實現面向對象的三層結構應用系統的方法。
關鍵詞 ASP.NET; 三層結構; UML建模; 系統開發
架構設計是軟件開發的基礎,並往往決定一個項目的成敗。三層結構是目前流行的架構設計模式,它是在由Buschmann等提出的“層模式”[1]基礎上發展起來的,由表示層、業務邏輯層和數據訪問層三個層次結構組成。它通過分解來管理問題的復雜性,同時還可以有效地重復使用業務邏輯並保留與昂貴資源(如數據庫)的重要連接[2,3]。
基於ASP.NET能夠充分發揮其完全面向對象的技術特點,實現三層結構B/S系統架構,從而提高開發效率,增強系統的可維護性和擴展性。本文結合一個“學生成績管理系統”的開發,研究如何基於UML進行三層B/S結構的系統建模,及其在ASP.NET下的應用實現。
1 三層結構系統模型
架構設計是非常高級的設計,也是系統設計的關鍵,主要是定義和說明包(子系統),以及包與包之間的相互依賴與通信機制。系統構架模型的合理與否將決定系統的可維護性、擴展性和開發效率。
包通常所需要處理的是要么是一個具體的功能區域(業務邏輯),要么是一個具體的技術區域(技術邏輯)。業務邏輯主要考慮的是對系統業務功能的實現,而技術邏輯則是進一步考慮用戶界面、數據庫或通信機制等形成的技術方案。把技術邏輯和業務邏輯區分開來是極其重要的,這是為了當修改程序的某一部分時不會對另一部分產生影響,更加便於進行“復用”,同時易於應對來自業務邏輯的變更需求。
三層結構是一種成熟、簡單並得到普遍應用的應用程序架構,它將應用程序結構划分三層獨立的包,包括用戶表示層、業務邏輯層、數據訪問層。其中將實現人機界面的所有表單和組件放在表示層,將所有業務規則和邏輯的實現封裝在負責業務邏輯組件中,將所有和數據庫的交互封裝在數據訪問組件中。其結構如下圖1所示:
圖1 三層結構示意圖
三層結構是一種嚴格分層方法,即數據訪問層只能被業務邏輯層訪問,業務邏輯層只能被表示層訪問,用戶通過表示層將請求傳送給業務邏輯層,業務邏輯層完成相關業務規則和邏輯,並通過數據訪問層訪問數據庫獲得數據,然后按照相反的順序依次返回將數據顯示在表示層。
2 三層B/S結構的學生管理系統開發
下面通過一個學生管理系統的開發,說明三層B/S結構系統從UML建模到基於ASP.NET進行實現的完整開發過程,UML建模工具采用的是Rational Rose。
2.1 需求分析
軟件需求分析是系統開發的第一步也是最重要的一個環節,其基本任務是准確地回答“系統做什么?”這個問題,這需要在對用戶需求進行充分調研的基礎上,深入理解並描述出軟件的功能、性能、接口等方面的需求,可以使用UML建模作為需求分析和系統設計的有效方法。
分析的目的是為了獲得和描述系統中所有的要求,因此分析階段是一種典型的與用戶或客戶合作的過程,通常由開發人員同用戶或客戶共同完成。在這個階段,開發人員不應該考慮代碼或程序實現的細節,而應該把精力放在對現有業務邏輯的理解上,通過與用戶之間的充分溝通,逐步理解並描述出得到用戶確認的系統模型,包括用例模型和領域(domain,系統中關鍵的類)模型。
2.1.1 用例模型
軟件開發人員在對用戶進行需求調研的過程中,用戶往往並不能立即准確描述出未來系統應該提供一些什么樣的功能。因此,需要開發人員理解和分析需求,並將系統應該具有的功能通過用例圖直觀的描述出來,方便用戶理解並做出評判,開發人員從而可以根據用戶的反饋不斷調整用例模型,直至完全正確、充分描述清楚系統功能。
用例建模主要是分離出系統的活動參與者(Actor)和用例(Use Case),用例是指對系統提供的功能的一種描述,而活動參與者是那些可能使用這些用例的人或外部系統,通過用例圖可以描述出系統外部的執行者、系統的用例,以及它們之間的聯系。本學生管理系統的用例圖見圖2。
用例模型還需要進一步對每個用例進行詳細描述,進一步說明用例的名稱、基本事件流和備選事件流、前置條件和后置條件等,並形成文檔。限於篇幅,這里就不多說了。
圖2 用例圖
2.1.2 領域建模
分析過程中還要詳細地列舉領域(domain ,系統中關鍵的類),為了進行領域分析,需要充分理解用例模型,也可以與用戶及領域專家組織一次集體研討會談,嘗試找出所有必須處理的關鍵概念以及它們之間的相互關系,並最終分析出域類圖。下圖3為本系統的域類圖。
需要強調的是:在本階段,對領域進行分析的類圖還是處於“草圖”狀態。定義的操作和屬性不是最后的版本,只是在本階段看來比較合適。后期將通過動態行為分析不斷得出新的操作,這是一個逐步完善和發展的過程。
2.2 系統設計
系統設計的目的是產生一個可用的、完整的解決方案,並且能夠比較容易地將方案轉換成程序代碼。這個階段在三層結構的架構設計模型基礎上,將考慮所有的實現技術問題,對分析階段的模型進行擴展和細化,分析階段定義的類進一步擴充,定義新的類來處理技術方面的問題,並形成最后的UML模型。
推動不斷進行詳細設計的方法是對每個用例進行動態建模,描述如何通過類圖中的對象協作實現用例中的功能,由於一開始對系統的認識是很不夠的,前面建立的類往往隨着動態建模的深入,發現存在缺陷或不夠完整,需要對分析中得到的域類圖進行不斷修正和調整,擴展形成業務邏輯包。同時,隨着對用戶界面、數據庫訪問等技術實現的深入建模,不斷建立新的用戶界面類(如窗體、控件)和數據訪問類,形成用戶界面包和數據訪問包。
本學生管理系統經過詳細設計后,在域類圖基礎上進行擴展后形成的業務邏輯包類圖如下圖4所示。
圖3 域類圖
圖4 業務邏輯包類圖
新建立的數據訪問包類圖如下圖5所示。所有的數據訪問類都定義了一個基類DBCommon,該基類包含屬性DBConnectionString,通過該屬性可以獲得數據庫連接字符串。還包括一個方法GetDataView,可以實現在數據庫中執行查詢獲得一個DataView。這些屬性和方法被所有的數據訪問類繼承,可以直接使用。
圖5 數據訪問包
關於用戶界面包的類圖比較簡單,主要是通過界面設計,設計出窗體及控件等界面元素,並根據動態建模時需要涉及的用戶界面訪問動作,定義所引起的相關事件,這些方面都在窗體類中進行定義,並組成用戶界面包,這里就不詳細介紹。
動態建模通常采用的方法是使用UML中的時序圖描述用例,一個時序圖針對某個用例中的一個“場景”進行分析。所謂“場景”是指一個用例中事件發展的一條路線。根據活動參與者的不同輸入或行為,通常一個用例會有多個“場景”,也就需要分析出多個時序圖。通過時序圖描述一個場景中各個對象之間所進行的通信,同時可以分析出系統中相應的類需要具備的操作,從而不斷擴充和細化類的設計。如果需要進一步描述類的狀態變化情況和操作流程,可以使用UML中的狀態圖和活動圖。
圖6 登錄場景
動態建模時產生的時序圖較多,這里無法一一闡述。圖6給出了登錄系統場景的時序圖,在用戶界面包中定義了一個LoginForm類,其對應的Web窗體為用戶登錄窗體頁面Login.aspx,圖6描述了在該窗體中實現用戶登錄的場景。
2.3 基於ASP.NET的系統實現
前面系統設計動態模型時,通過時序圖已經對每個用例的各項功能所涉及的場景進行了詳盡的描述,按照時序圖的規定把每個用例都分別進行編碼實現即可。下面結合學生管理系統中的“登錄系統”用例,介紹基於ASP.NET進行系統實現的方法。
首先需要考慮分包,ASP.NET中包對應的就是命名空間。在本學生管理系統中,規定業務邏輯包的命名空間為ResultManage.BusinessRule,數據訪問包的命名空間為ResultManage.DataAccess,而用戶界面包的命名空間為ResultManage.Web。
然后進行業務邏輯包和數據訪問包中相關類的設計,對於“登錄系統”用例,從上圖6的登錄場景時序圖中可以看出,相關的類有業務邏輯包的Users類和數據訪問包的UsersDB類,分別對這些類的屬性和方法進行定義和實現,並設計一些測試用例或測試程序對其進行單元測試。
最后按照用戶界面包和上圖6的登錄場景時序圖中的規定,對用戶登錄窗體頁面Login.aspx進行設計實現,其實現登錄的代碼如下所示:
private void btnLogin_Click(object sender, System.EventArgs e)
{
//獲得用戶登錄信息
string UserName = txbUserName.Text;
string Password = txbPassword.Text;
try
{
if (Users.Login(UserName , Password)) //檢查用戶登錄信息
{
//創建身份驗證票
FormsAuthentication.SetAuthCookie(UserName, false);
//顯示歡迎信息
ShowWelcomeMessage(UserName);
}
else
{
Message.Text = "用戶登錄失敗!";
}
}
catch (SqlException sqlexception)
{
//提示數據庫操作錯誤信息
Response.Write(sqlexception.Message);
}
}
代碼中對於業務的處理,通過調用業務邏輯包Users類的Login方法實現登錄信息的檢查,其代碼如下:
public static bool Login(string UserName , string Password)
{
if (UserName == "")
{
return false;
}
else
{
//檢查數據庫中是否存在符合的用戶
return UsersDB.CheckLogin(UserName , Password);
}
}
上述Users類的Login方法的代碼中,首先進行業務邏輯檢查,判斷用戶名是否為空,涉及數據庫訪問則通過數據訪問類完成,通過數據訪問包的UsersDB類的CheckLogin方法從數據庫中檢查是否存在符合相應登錄信息的用戶。
前面已經提到,包括UsersDB類在內的數據訪問層所有類都從一個基類DBCommon繼承,該基類封裝了所有數據庫訪問類公共的特性,其中包括定義了公共屬性:數據連接字符串DBConnectionString。UsersDB類的CheckLogin方法中使用DBConnectionString進行數據庫的連接,並調用數據庫中存儲過程CheckLogin查找用戶登錄信息是否正確。
3 結束語
本文介紹了三層B/S結構系統的UML建模和基於ASP.NET進行實現的過程和方法,實現的三層結構不僅程序邏輯上結構清晰,而且由於容易發生需求變更的業務邏輯部分實現了分離,因此具有更強的可擴展性和可維護性。同時這種系統在部署時具有很強的靈活性,可以將各個包分別編譯成.NET組件,安裝在多台服務器。較典型的是用戶界面包安裝在Web服務器,業務邏輯包安裝在應用服務器,數據訪問包安裝在數據庫服務器或進一步分離,從而實現多級分布的部署方式,實現更好的可伸縮性和安全性,滿足大規模的企業級B/S應用系統的需求。
- 22:54
- 評論 / 瀏覽 (0 / 749)
一、數據庫
/* DBMS name: Microsoft SQL Server 2000 */
if exists (select 1
from sysobjects
where id = object_id('newsContent')
and type = 'U')
drop table newsContent
go
/* Table: newsContent */
create table newsContent (
ID int identity(1,1) primary key,
Title nvarchar(50) not null,
Content ntext not null,
AddDate datetime not null,
CategoryID int not null
)
go
二、項目文件架構
實現步驟為:4-3-6-5-2-1
ID
項目
描述
用途
項目引用關系
實例所需文件
相關方法
1
Web
表現層
Web頁和控件
引用BLL
WebUI.aspx
WebUI.aspx.cs
GetContent()
2
BLL
業務邏輯層
業務邏輯組件
引用 IDAL,Model,使用DALFactory創建實例
Content.cs
ContentInfo GetContentInfo(int id)
3
IDAL
數據訪問層接口定義
每個DAL實現都要實現的一組接口
引用 Model
IContent.cs
ContentInfo GetContentInfo(int id)
4
Model
業務實體
傳遞各種數據的容器
無引用
ContentInfo.cs
5
DALFactory
數據層的抽象工廠
創建反射,用來確定加載哪一個數據庫訪問程序集的類
引用IDAL,通過讀取web.config里設置的程序集,加載類的實例,返回給BLL使用。
Content.cs
IDAL.Icontent create()
6
SQLServerDAL
SQLServer數據訪問層
Microsoft SQL Server特定的Pet Shop DAL實現,使用了IDAL接口
引用 Model和IDAL,被DALFactory加載的程序集,實現接口里的方法。
SqlHelper.cs
Content.cs
SqlDataReader ExecuteReader()
PrepareCommand()
ContentInfo GetContentInfo(int id)
OracleDAL
Oracle數據訪問層
7
DBUtility
數據庫訪問組件基礎類
GetSqlServerConnectionString得到數據庫連接字符串,也可省去該項目,在SQLServerDAL.SqlHelper中用static readonly string SqlConnectionString代替。
無引用
實現步驟過程
1、創建Model,實現業務實體。
2、創建IDAL,實現接口。
3、創建SQLServerDAL,實現接口里的方法。
4、增加web.config里的配置信息,為SQLServerDAL的程序集。
5、創建DALFactory,返回程序集的指定類的實例。
6、創建BLL,調用DALFactory,得到程序集指定類的實例,完成數據操作方法。
7、創建WEB,調用BLL里的數據操作方法。
注意:
1、web.config里的程序集名稱必須與SQLServerDAL里的輸出程序集名稱一致。
2、DALFactory里只需要一個DataAccess類,可以完成創建所有的程序集實例。
3、項目創建后,注意修改各項目的默認命名空間和程序集名稱。
4、注意修改解決方案里的項目依賴。
5、注意在解決方案里增加各項目引用。
三、各間的訪問過程
1、傳入值,將值進行類型轉換(為整型)。
2、創建BLL層的content.cs對象c,通過對象c訪問BLL層的方法GetContentInfo(ID)調用BLL層。
3、BLL層方法GetContentInfo(ID)中取得數據訪問層SQLServerDAL的實例,實例化IDAL層的接口對象dal,這個對象是由工廠層DALFactory創建的,然后返回IDAL層傳入值所查找的內容的方法dal.GetContentInfo(id)。
4、數據工廠通過web.config配置文件中給定的webdal字串訪問SQLServerDAL層,返回一個完整的調用SQLServerDAL層的路徑給 BLL層。
5、到此要調用SQLServerDAL層,SQLServerDAL層完成賦值Model層的對象值為空,給定一個參數,調用SQLServerDAL層的SqlHelper的ExecuteReader方法,讀出每個字段的數據賦值給以定義為空的Model層的對象。
6、SqlHelper執行sql命令,返回一個指定連接的數據庫記錄集,在這里需要引用參數類型,提供為打開連接命令執行做好准備PrepareCommand。
7、返回Model層把查詢得到的一行記錄值賦值給SQLServerDAL層的引入的Model層的對象ci,然后把這個對象返回給BLL。
8、回到Web層的BLL層的方法調用,把得到的對象值賦值給Lable標簽,在前台顯示給界面
四、項目中的文件清單
1、DBUtility項目
(1)connectionInfo.cs
using System;
using System.Configuration;
namespace Utility
{
/// <summary>
/// ConnectionInfo 的摘要說明。
/// </summary>
public class ConnectionInfo
{
public static string GetSqlServerConnectionString()
{
return ConfigurationSettings.AppSettings["SQLConnString"];
}
}
}
2、SQLServerDAL項目
(1)SqlHelper.cs抽象類
using System;
using System.Data;
using System.Data.SqlClient;
using DBUtility;
namespace SQLServerDAL
{
/// <summary>
/// SqlHelper 的摘要說明。
/// </summary>
public abstract class SqlHelper
{
public static readonly string CONN_STR = ConnectionInfo.GetSqlServerConnectionString();
/// <summary>
/// 用提供的函數,執行SQL命令,返回一個從指定連接的數據庫記錄集
/// </summary>
/// <remarks>
/// 例如:
/// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">SqlConnection有效的SQL連接字符串</param>
/// <param name="commandType">CommandType:CommandType.Text、CommandType.StoredProcedure</param>
/// <param name="commandText">SQL語句或存儲過程</param>
/// <param name="commandParameters">SqlParameter[]參數數組</param>
/// <returns>SqlDataReader:執行結果的記錄集</returns>
public static SqlDataReader ExecuteReader(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)
{
SqlCommand cmd = new SqlCommand();
SqlConnection conn = new SqlConnection(connString);
// 我們在這里用 try/catch 是因為如果這個方法拋出異常,我們目的是關閉數據庫連接,再拋出異常,
// 因為這時不會有DataReader存在,此后commandBehaviour.CloseConnection將不會工作。
try
{
PrepareCommand(cmd, conn, null, cmdType, cmdText, cmdParms);
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
return rdr;
}
catch
{
conn.Close();
throw;
}
}
/// <summary>
/// 為執行命令做好准備:打開數據庫連接,命令語句,設置命令類型(SQL語句或存儲過程),函數語取。
/// </summary>
/// <param name="cmd">SqlCommand 組件</param>
/// <param name="conn">SqlConnection 組件</param>
/// <param name="trans">SqlTransaction 組件,可以為null</param>
/// <param name="cmdType">語句類型:CommandType.Text、CommandType.StoredProcedure</param>
/// <param name="cmdText">SQL語句,可以為存儲過程</param>
/// <param name="cmdParms">SQL參數數組</param>
private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
{
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Connection = conn;
cmd.CommandText = cmdText;
if (trans != null)
cmd.Transaction = trans;
cmd.CommandType = cmdType;
if (cmdParms != null)
{
foreach (SqlParameter parm in cmdParms)
cmd.Parameters.Add(parm);
}
}
}
}
(2)Content.cs類
using System;
using System.Data;
using System.Data.SqlClient;
using Model;
using IDAL;
namespace SQLServerDAL
{
/// <summary>
/// Content 的摘要說明。
/// </summary>
public class Content:IContent
{
private const string PARM_ID = "@ID";
private const string SQL_SELECT_CONTENT = "Select ID, Title, Content, AddDate, CategoryID From newsContent Where ID = @ID";
public ContentInfo GetContentInfo(int id)
{
//創意文章內容類
ContentInfo ci = null;
//創建一個參數
SqlParameter parm = new SqlParameter(PARM_ID, SqlDbType.BigInt, 8);
//賦上ID值
parm.Value = id;
using(SqlDataReader sdr = SqlHelper.ExecuteReader(SqlHelper.CONN_STR, CommandType.Text, SQL_SELECT_CONTENT, parm))
{
if(sdr.Read())
{
ci = new ContentInfo(sdr.GetInt32(0),sdr.GetString(1), sdr.GetString(2),
sdr.GetDateTime(3), sdr.GetInt32(4), sdr.GetInt32(5), sdr.GetString(6));
}
}
return ci;
}
}
}
3、Model項目
(1)contentInfo.cs
using System;
namespace Model
{
/// <summary>
/// Class1 的摘要說明。
/// </summary>
public class ContentInfo
{
private int _ID;
private string _Content;
private string _Title;
private string _From;
private DateTime _AddDate;
private int _clsID;
private int _tmpID;
/// <summary>
/// 文章內容構造函數
/// </summary>
/// <param name="id">文章流水號ID</param>
/// <param name="content">文章內容</param>
/// <param name="title">文章標題</param>
/// <param name="from">文章來源</param>
/// <param name="clsid">文章的分類屬性ID</param>
/// <param name="tmpid">文章的模板屬性ID</param>
public ContentInfo(int id,string title,string content,string from,DateTime addDate,int clsid,int tmpid )
{
this._ID = id;
this._Content = content;
this._Title = title;
this._From = from;
this._AddDate = addDate;
this._clsID = clsid;
this._tmpID = tmpid;
}
//屬性
public int ID
{
get { return _ID; }
}
public string Content
{
get { return _Content; }
}
public string Title
{
get { return _Title; }
}
public string From
{
get { return _From; }
}
public DateTime AddDate
{
get { return _AddDate; }
}
public int ClsID
{
get { return _clsID; }
}
public int TmpID
{
get { return _tmpID; }
}
}
}
4、IDAL項目
(1)Icontent.cs
using System;
using Model;
namespace IDAL
{
/// <summary>
/// 文章內容操作接口
/// </summary>
public interface IContent
{
/// <summary>
/// 取得文章的內容。
/// </summary>
/// <param name="id">文章的ID</param>
/// <returns></returns>
ContentInfo GetContentInfo(int id);
}
}
5、DALFactory項目
(1)Content.cs
using System;
using System.Reflection;
using System.Configuration;
using IDAL;
namespace DALFactory
{
/// <summary>
/// 工產模式實現文章接口。
/// </summary>
public class Content
{
public static IDAL.IContent Create()
{
// 這里可以查看 DAL 接口類。
string path = System.Configuration.ConfigurationSettings.AppSettings["WebDAL"].ToString();
string className = path+".Content";
// 用配置文件指定的類組合
return (IDAL.IContent)Assembly.Load(path).CreateInstance(className);
}
}
}
6、BLL項目
(1)Content.cs
using System;
using Model;
using IDAL;
namespace BLL
{
/// <summary>
/// Content 的摘要說明。
/// </summary>
public class Content
{
public ContentInfo GetContentInfo(int id)
{
// 取得從數據訪問層取得一個文章內容實例
IContent dal = DALFactory.Content.Create();
// 用DAL查找文章內容
return dal.GetContentInfo(id);
}
}
}
7、Web項目
1、Web.config:
<appSettings>
<add key="SQLConnString" value="Data Source=localhost;Persist Security info=True;Initial Catalog=newsDB;User ID=sa;Password= " />
<add key="WebDAL" value="SQLServerDAL" />
</appSettings>
2、WebUI.aspx
<%@ Page language="c#" Codebehind="WebUI.aspx.cs" AutoEventWireup="false" Inherits="Web.WebUI" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebUI</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<FONT">宋體"></FONT>
<table width="600" border="1">
<tr>
<td style="WIDTH: 173px"> </td>
<td>
<asp:Label id="lblTitle" runat="server"></asp:Label></td>
</tr>
<tr>
<td style="WIDTH: 173px; HEIGHT: 22px"> </td>
<td style="HEIGHT: 22px">
<asp:Label id="lblDataTime" runat="server"></asp:Label></td>
</tr>
<tr>
<td style="WIDTH: 173px"> </td>
<td>
<asp:Label id="lblContent" runat="server"></asp:Label></td>
</tr>
<tr>
<td style="WIDTH: 173px"> </td>
<td> </td>
</tr>
<tr>
<td style="WIDTH: 173px; HEIGHT: 23px"> </td>
<td style="HEIGHT: 23px"> </td>
</tr>
<tr>
<td style="WIDTH: 173px"> </td>
<td> </td>
</tr>
<tr>
<td style="WIDTH: 173px"> </td>
<td> </td>
</tr>
<tr>
<td style="WIDTH: 173px"> </td>
<td> </td>
</tr>
<tr>
<td style="WIDTH: 173px"> </td>
<td>
<asp:Label id="lblMsg" runat="server">Label</asp:Label></td>
</tr>
</table>
</form>
</body>
</HTML>