基于asp.net的Web开发架构探索(转)
問題由來
最近在研究適合團隊開發的web架構解決方案,該架構即要適合分工協作又要有一定擴展性,適合不同的數據庫需要,因此我查閱了一些資料,初步構想出了一套架構,請各位多多指教。
?
探索
web開發架構最經典莫過于三層架構,表示層、邏輯層、數據處理層。
數據訪問層:其功能主要是負責數據庫的訪問。
業務邏輯層:是整個系統的核心,它與這個系統的業務(領域)有關。
表示層:是系統的UI部分,負責使用者與整個系統的交互。理想的狀態是表示層不應包括系統的業務邏輯。
這些是經典的解釋,如果要適合不同的數據庫則需要加入工廠模式,里面用面向接口的方式進行多態調用。是不是這有點像petshop了。所以架構的初步設想是這樣:
下面以獲取用戶信息為例,簡述這個架構的流程:(以下為類似petshop的經典做法,了解的可以略過)
step 1 、首先我們應該建立項目所需的實體模型,在這里新建用戶信息的實體模式,UserInfo.cs。該類保存在Model項目里。
step 2 、我們再將項目的單元功能寫到相關的接口中,這里以獲取用戶信息功能為例。在IDAL項目里新建IUser接口。
??????? //根據用戶ID獲取用戶信息
??????? UserInfo GetUserById(int userId);
step 3、完成了接口,我們就要實現它,現在我們用sqlserver、oracle兩種數據庫訪問方式來實現它。以下是SqlserverDAL中User類對接口的現實:
public class User:IUser
??? {
???????
??????? public UserInfo GetUserById(int userId)
??????? {
???????? //實現操作???????????
??????? }
??? }
OracleDAL中現實方式類似。。。。
step 4、在此數據庫訪問層應該就基本寫好了,下面應該給邏輯層調用了,但是兩種實現方式怎么調用呢,或者說怎么有選擇的調用它呢,petshop是這樣處理的,在DALFactory中的DataAccess類,利用反射載入程序集從而實例化所需要的類:
??????? private static readonly string path = ConfigurationManager.AppSettings["WebDAL"];
??????? public static IUser CreateUser()
??????? {??
??????????? string className = path + ".User";
??????????? return (IUser)Assembly.Load(path).CreateInstance(className);
??????? }
至于要選擇哪個數據庫訪問層,在配置文件里配置一下WebDAL。如:<add key="WebDAL" value="SQLServerDAL"/>。
這樣就基本解決了邏輯層和數據訪問層的耦合。
step 5、下面就該寫邏輯層了,在BLL里面創建User.cs類。大致如下:
public class User
?? {
?????? private static readonly IUser dal = DALFactory.DataAccess.CreateUser();
?????? public UserInfo GetUserInfo(int userId) {
??????????? return dal.GetUserById(userId);
??????? }
?? }
是不是覺得BLL毫無意義,因為它只是對數據訪問層方法的簡單調用,但并不是這樣的,這里只有一個簡單的事例,在實際項目中一個BLL里面處理的可能是一個非常復雜的邏輯,而這個復雜邏輯的結果才提供給表示層顯示。
step 6、最后是表示層,好像沒什么可說的,把從BLL取出來的數據綁定到你的頁面就行了。
以上是仿petshop的架構設計,看起來沒什么質疑的地方,畢竟是微軟的經典案例。你可能抱怨的地方有兩點,一是層是不是有點多,關系過于復雜;二如果我需要改變或增加一個數據庫字段,那不是會很痛苦,因為要節聯修改。這兩個問題,我都沒辦法解決,一如果說過于層過于多而繁瑣,那么下面我寫的好像更為復雜,原諒。。。。二、鄙人覺得凡是分層開發,只要以數據庫字段為依據的建立實體模型,都會存在節聯修改的問題。除非全部用DataTable,那么在BLL、表示層調用的時候并不知道DataTable到底裝有什么,這樣無疑更加了調用的不便利。關于減少節聯修改的問題,如有解決方法的請指教。
對以上架構的修改
我重點分析了以上架構的數據訪問工廠的設計部分,即DALFactory中的DataAccess類。在此類中,實現了對不同數據庫訪問層的調用
。但如果現在有一個項目,里面有sqlserver又有oracle的現實,我們是不是要這樣做:
private static readonly string path = ConfigurationManager.AppSettings["WebDAL"];//對sqlserver數據庫訪問層的調用
private static readonly string path2 = ConfigurationManager.AppSettings["WebDAL2"];//對oracel數據庫訪問層的調用
??????? public static IUser CreateUser()
??????? {??
??????????? string className = path + ".User";
??????????? return (IUser)Assembly.Load(path).CreateInstance(className);
??????? }
??????? public static IOrder CreateOrder()
??????? {??
??????????? string className = path2 + ".Order";
??????????? return (IUser)Assembly.Load(path2).CreateInstance(className);
??????? }
如果要創建其他的訪問類,我們還要寫CreateProduct(),CreateArticle,CreateMenu。。。。。那么這樣的類會很繁瑣,我們能不能
只做一個方法,其他的工作只需要開發人員通過配置文件來完成呢。我的解決方案有兩個:
一、Spring.net
這個東西就是專門用來解耦合的,我們將它的相關程序集加載到DALFactory中,于是在DataAccess中,我們可以做:
private static readonly string configPath = HttpContext.Current.Request.PhysicalApplicationPath +
ConfigurationManager.AppSettings["objectconfig"];//這是spring.net的對象配置文件在服務器上的物理位置
??????? public static T CreateObject<T>()
??????? {
??????????? IResource rs = new FileSystemResource(configPath);
??????????? IObjectFactory factory = new XmlObjectFactory(rs);
??????????? string id = typeof(T).FullName;
??????????? return (T)factory.GetObject(id);
}
這里我們傳入一個泛型,讓spring.net在它的對象配置文件里面找到該類型的程序集并加載,創建出對應的對象。objectconfig文件
大致如下:
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net"/
??? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
??? xsi:schemaLocation="http://www.springframework.net/
http://www.springframework.net/xsd/spring-objects.xsd">
<object id="IDAL.IUser" type="SQLServerDAL.Function"></object>
</objects>
這樣在BLL 就這樣調用
private static readonly IUser dal = EtourAF.Shared.DALFactory.DataAccess.CreateObject<IUser>();
這樣開發人員如果要加入一個對象就在object-config中加一段相關配置就行了。嘿嘿,這就變成了petshop+spring.net了,YY無極限。。。。
二、也是用反射
這里我們只是用了一個鍵值對的方式,照例在配置文件里配置相應的接口和對象,只是我們把他配置到了web.config當中:
<add key="IDAL.IUser" value="SQLServerDAL.Function" />
在DataAccess中,我們就這樣寫:
public static T CreateObject<T>()
??????? {
??????????? string interfaceFullName = typeof(T).FullName;
??????????? string className = ConfigurationManager.AppSettings[interfaceFullName];
??????????? string nameSpace = className.Substring(0, className.LastIndexOf("."));
??????????? return (T)Assembly.Load(nameSpace).CreateInstance(className);
??????? }
可能有人說
string nameSpace = className.Substring(0, className.LastIndexOf("."));這里這個截取是不是覺得有點硬,我現在也只想到這個辦法,但絕對不會有問題的。
好了,這些大概就是鄙人這兩天的有些收獲,請指教。
轉載于:https://www.cnblogs.com/aaa6818162/archive/2009/08/05/1539246.html
總結
以上是生活随笔為你收集整理的基于asp.net的Web开发架构探索(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019_7_31python
- 下一篇: PL/SQL Developer 9 注