日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实战分层架构

發布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实战分层架构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

現在可選的框架

??? 現在我們開發一個.net應用,面臨的選擇比較多。我們可以選擇entity framework, enterprise library, nhibernate, 還有一個mybatis.net, 即java世界mybatis/ibatis的.net版。?IOC的框架可以選擇Unity, Ninject,Spring.net(java的spring對應的.net版本)。Entity framework可以使用linq查詢,有好幾種開發模式,如code first, db first, 可以不用寫sql。Entity framework適合sql server。雖有mysql提供了entity framework的provider,但是不是很好, 經常不得不單獨寫sql來操作mysql. Enterprise library是個不錯的選擇,有log, exception, policy injection的一些東西,操作數據庫也比較好。nhibernate是java版hibernate的.net對應版本。對數據庫包裝得比較多,可以不用寫sql. 但是有些時候對數據庫操作不夠優化,會有一些多余數據庫操作。帶來一些性能的影響。mybatis.net是個介于ado.net與nhibernate之間的框架,它負責數據庫對象與內存對象的映射。程序員必須寫sql語句來操作數據庫。IOC的框架中Unity, Ninject, Spring.net, 都是不錯的框架。有時這些框架能照顧到我們大部分的需求,也有一些情況,不能全部照顧到我們的需求。這時就得用一些老辦法。比如直接就用ado.net

適應多種數據庫的db helper代碼

??? 這里主要是想說一些基于ado.net來開發asp.net mvc應用的一些思路。為什么選用ado.net呢,ado.net性能可以達到最好,靈活。先看一段db helper的代碼:

using System; using System.Configuration; using System.Data; using System.Data.Common; using System.Collections.Generic;namespace DataAccessCommon {/// <summary>/// The MyDBHelper class is intended to encapsulate high performance, scalable best practices for /// common uses of SqlClient, OracleClient, OleDb, and others/// </summary>public static class MyStaticDBHelper{public struct MyDBParameter{public string strParameterName;public DbType dbType;public object value;public ParameterDirection parameterDirection;public MyDBParameter(string parameterName, DbType type, object theValue, ParameterDirection direction = ParameterDirection.Input){strParameterName = parameterName;dbType = type;value = theValue;parameterDirection = direction;}}public static string DatabaseType = "SqlServer";private static Dictionary<string, string> providers = new Dictionary<string, string>() {{ "SqlServer", "System.Data.SqlClient" }, { "Oracle", "System.Data.OracleClient" }, { "OleDb", "System.Data.OleDb" } };private static DbProviderFactory dataFactory = DbProviderFactories.GetFactory(providers[DatabaseType]);public static string CONNECTION_STRING = ConfigurationManager.AppSettings["ConnectionString"];#region private methodsprivate static void AttachParameters(DbCommand command, DbParameter[] parameters){if (parameters != null){command.Parameters.AddRange(parameters);}}private static DbCommand CreateCommand(object conn){DbCommand command = null;//If it is just a connection(not a transaction)if (conn is DbConnection){command = ((DbConnection)conn).CreateCommand();if (command.Connection.State != ConnectionState.Open){command.Connection.Open();}}else //It is a transaction, then join the transaction {command = ((DbTransaction)conn).Connection.CreateCommand();command.Transaction = (DbTransaction)conn;}return command;}private static DbCommand SetupCommand(object conn, CommandType commandType, string strSQLOrSPName, List<MyDBParameter> myDBParameters){DbParameter[] parameters = myDBParameters != null ? CreateDBParameters(myDBParameters).ToArray() : null;DbCommand command = CreateCommand(conn);command.CommandText = strSQLOrSPName;command.CommandType = commandType;AttachParameters(command, parameters);return command;}private static DbParameter CreateDBParameter(string strParameterName, DbType dbType, object value, ParameterDirection direction){DbParameter parameter = dataFactory.CreateParameter();parameter.ParameterName = strParameterName;parameter.DbType = dbType;parameter.Value = value;parameter.Direction = direction;return parameter;}private static List<DbParameter> CreateDBParameters(List<MyDBParameter> myDBParameters){List<DbParameter> parameters = new List<DbParameter>();foreach (MyDBParameter myDBParameter in myDBParameters){parameters.Add(CreateDBParameter(myDBParameter.strParameterName, myDBParameter.dbType, myDBParameter.value, myDBParameter.parameterDirection));}return parameters;}#endregionpublic static DbConnection GetConnection(){DbConnection connection = dataFactory.CreateConnection();connection.ConnectionString = CONNECTION_STRING;return connection;}public static int ExecuteNonQuery(object conn, CommandType commandType, string strSQLOrSPName, List<MyDBParameter> myDBParameters = null){DbCommand command = SetupCommand(conn, commandType, strSQLOrSPName, myDBParameters);return command.ExecuteNonQuery();}public static DataSet ExecuteDataset(object conn, CommandType commandType, string strSQLOrSPName, List<MyDBParameter> myDBParameters = null){DbCommand command = SetupCommand(conn, commandType, strSQLOrSPName, myDBParameters);DbDataAdapter dataAdaptor = dataFactory.CreateDataAdapter();DataSet ds = new DataSet();dataAdaptor.SelectCommand = command;dataAdaptor.Fill(ds);return ds;}public static DbDataReader ExecuteReader(object conn, CommandType commandType, string strSQLOrSPName, List<MyDBParameter> myDBParameters = null){DbCommand command = SetupCommand(conn, commandType, strSQLOrSPName, myDBParameters);return command.ExecuteReader();}public static object ExecuteScalar(object conn, CommandType commandType, string strSQLOrSPName, List<MyDBParameter> myDBParameters = null){DbCommand command = SetupCommand(conn, commandType, strSQLOrSPName, myDBParameters);return command.ExecuteScalar();}} }

此代碼能支持訪問Oracle, sql server, OleDB。用的都是DbConnection之類的。只要開始選擇了正確的provider, DbProviderFactories就給創建相應的connection, command等類,就可以順利地處理這個對應的數據庫了。sql的參數是DbType。用來適應數據庫類型。MyDBParameter結構封裝了參數名,類型,參數值,傳入傳出方向。目前的版本只考慮了一個數據庫連接。連接串只有一個。DbProviderFactory只有一個實例。沒有考慮到動態切換連接的情況。如果是要多個連接,得要多個DbProviderFactory的實例。CreateCommand方法里判斷了傳入的的數據庫連接是一個DbConnection還是一個DbTransaction,如果是一個DbTransaction的話,可以加入這個數據庫事務。如果只是一個DbConnection則不加入已有的數據庫事務,使用自動的數據庫事務。

數據實體類

using System; using System.Collections.Generic;namespace DataEntity {public class UserMenuItem{#region Propertiespublic int MenuItemID { get; set; }public string MenuItemName { get; set; }public int MenuID { get; set; }public int Ordinal { get; set; }public int Indent { get; set; }#endregion} }

純數據的類。這里使用了比較老的c#語法。也可以加上DataAnnotation的標簽。可以實現驗證數據,也可以加上Display標簽,引用資源文件。這個數據實體類在MVC頁面里綁定時可以顯示想應的label。label的內容來自于資源文件,便于使用多語言的界面。

using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Resource.Entity;namespace DataEntity {public class UserAccount{#region Propertiespublic int ID { get; set; }[Required(ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName="Common_Required_ErrorMessage")][StringLength(30, ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "NAME_StringLength_ErrorMessage")][RegularExpression(@"[a-zA-Z].*", ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "NAME_RegularExpression_ErrorMessage")][Display(ResourceType=typeof(Resource.Entity.UserAccount), Name="NAME_DisplayName")]public string Name { get; set; }[Required(ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")][RegularExpression(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName="EMAIL_RegularExpression_ErrorMessage")][Display(ResourceType=typeof(Resource.Entity.UserAccount), Name="EMAIL_DisplayName")]public string Email { get; set; }[Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "PASSWORD_DisplayName")][Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")][StringLength(32, ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "PASSWORD_StringLength", MinimumLength = 8)]public string Password { get; set; }[Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "Balance")]public decimal Balance { get; set; }[Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")][Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "CONFIRMPASSWORD_DisplayName")][Compare("Password", ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "CONFIRMPASSWORD_CompareErrorMessage")]public string ConfirmPassword { get; set; }[Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")][Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "OLDNAME_DisplayName")]public string OldName { get; set; }[Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")][Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "OLDEMAIL_DisplayName")]public string OldEmail { get; set; }[Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")][Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "OLDPassword_DisplayName")]public string OldPassword { get; set; }#endregion} }

?

下面是數據訪問的代碼:

using System; using System.Collections.Generic; using System.Data; using DataEntity; using DataAccessCommon;namespace DataAccess {public class DALUserMenuItem{#region data access methodspublic int DeleteUserMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuItemID", DbType.Int32, usermenuitem.MENUITEMID)};string strSQL = "DELETE FROM [UserMenuItem] WHERE [MenuItemID] = @MenuItemID";int result = 0;result = MyStaticDBHelper.ExecuteNonQuery(conn, System.Data.CommandType.Text, strSQL, paras);return result;}public int UpdateUserMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuItemName", DbType.String, usermenuitem.MENUITEMNAME),new MyStaticDBHelper.MyDBParameter("@MenuID", DbType.Int32, usermenuitem.MENUID),new MyStaticDBHelper.MyDBParameter("@Ordinal", DbType.Int32, usermenuitem.ORDINAL),new MyStaticDBHelper.MyDBParameter("@MenuItemID", DbType.Int32, usermenuitem.MENUITEMID)};string strSQL = "UPDATE [UserMenuItem] SET [MenuItemName] = @MenuItemName, [MenuID] = @MenuID, [Ordinal] = @Ordinal WHERE [MenuItemID] = @MenuItemID";int result = 0;result = MyStaticDBHelper.ExecuteNonQuery(conn, System.Data.CommandType.Text, strSQL, paras);return result;}public int AddUserMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuItemName", DbType.String, usermenuitem.MENUITEMNAME),new MyStaticDBHelper.MyDBParameter("@MenuID", DbType.Int32, usermenuitem.MENUID),new MyStaticDBHelper.MyDBParameter("@Ordinal", DbType.Int32, usermenuitem.ORDINAL),new MyStaticDBHelper.MyDBParameter("@MenuItemID", DbType.Int32, usermenuitem.MENUITEMID)};string strSQL = "INSERT INTO [UserMenuItem] ( [MenuItemName] , [MenuID] , [Ordinal] ) VALUES( @MenuItemName, @MenuID, @Ordinal ); SELECT SCOPE_IDENTITY() as [MenuItemID]";int result = 0;DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL, paras);if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0){usermenuitem.MENUITEMID = Convert.ToInt32(ds.Tables[0].Rows[0][0]);result = 1;}return result;}public List<UserMenuItem> GetAllUserMenuItem(Object conn){string strSQL = "SELECT * FROM [UserMenuItem] ";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL);return DataMapper.MapDataTableToObjectList<UserMenuItem>(ds.Tables[0]);}public UserMenuItem FindAUserMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuItemID", DbType.Int32, usermenuitem.MENUITEMID)};string strSQL = "SELECT * FROM [UserMenuItem] WHERE [MenuItemID] = @MenuItemID";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL, paras);return DataMapper.MapDataTableToSingleRow<UserMenuItem>(ds.Tables[0]);}public System.Int32 SelectCountUserMenuItem(Object conn){string strSQL = "SELECT COUNT(1) AS Count FROM [UserMenuItem] ";Object obj = null;obj = MyStaticDBHelper.ExecuteScalar(conn, System.Data.CommandType.Text, strSQL);return (System.Int32)obj;}public System.Int32 SelectCountWhereClauseUserMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuItemID", DbType.Int32, usermenuitem.MENUITEMID)};string strSQL = "SELECT COUNT(1) AS Count FROM [UserMenuItem] WHERE [MenuItemID] = @MenuItemID";Object obj = null;obj = MyStaticDBHelper.ExecuteScalar(conn, System.Data.CommandType.Text, strSQL, paras);return (System.Int32)obj;}public List<UserMenuItem> SelectTopUserMenuItem(Object conn){string strSQL = "SELECT Top 50 * FROM [UserMenuItem] ";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL);return DataMapper.MapDataTableToObjectList<UserMenuItem>(ds.Tables[0]);}public List<UserMenuItem> SelectOrderByPrimaryKeyUserMenuItem(Object conn){string strSQL = "SELECT * FROM [UserMenuItem] ORDER BY [MenuItemID] , [MenuItemName] , [MenuID] , [Ordinal]";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL);return DataMapper.MapDataTableToObjectList<UserMenuItem>(ds.Tables[0]);}public List<UserMenuItem> SelectGroupByPrimaryKeyUserMenuItem(Object conn){string strSQL = "SELECT * FROM [UserMenuItem] GROUP BY [MenuItemID] , [MenuItemName] , [MenuID] , [Ordinal]";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL);return DataMapper.MapDataTableToObjectList<UserMenuItem>(ds.Tables[0]);}public List<UserMenuItem> SelectUserMenuItemsByMenuID(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuID", DbType.Int32, usermenuitem.MENUID)};string strSQL = "SELECT * FROM [UserMenuItem] WHERE [MenuID] = @MenuID ORDER BY [Ordinal]";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL, paras);return DataMapper.MapDataTableToObjectList<UserMenuItem>(ds.Tables[0]);}public UserMenuItem SelectPreviousMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuID", DbType.Int32, usermenuitem.MENUID),new MyStaticDBHelper.MyDBParameter("@Ordinal", DbType.Int32, usermenuitem.ORDINAL)};string strSQL = "SELECT TOP 1 * FROM [UserMenuItem] WHERE [MenuID] = @MenuID AND [Ordinal] < @Ordinal ORDER BY [Ordinal] DESC";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL, paras);return DataMapper.MapDataTableToSingleRow<UserMenuItem>(ds.Tables[0]);}public UserMenuItem SelectNextMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuID", DbType.Int32, usermenuitem.MENUID),new MyStaticDBHelper.MyDBParameter("@Ordinal", DbType.Int32, usermenuitem.ORDINAL)};string strSQL = "SELECT TOP 1 * FROM [UserMenuItem] WHERE [MenuID] = @MenuID AND [Ordinal] > @Ordinal ORDER BY [Ordinal] ASC";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL, paras);return DataMapper.MapDataTableToSingleRow<UserMenuItem>(ds.Tables[0]);}public int MoveLeftMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuItemID", DbType.Int32, usermenuitem.MENUITEMID)};string strSQL = "UPDATE [UserMenuItem] SET [Indent] = CASE WHEN [Indent] - 1 >= 0 THEN [Indent] - 1 ELSE 0 END WHERE [MenuItemID] = @MenuItemID";int iResult = 0;iResult = MyStaticDBHelper.ExecuteNonQuery(conn, System.Data.CommandType.Text, strSQL, paras);return iResult;}public int MoveRightMenuItem(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuItemID", DbType.Int32, usermenuitem.MENUITEMID)};string strSQL = "UPDATE [UserMenuItem] SET [Indent] = CASE WHEN [Indent] + 1 <= 2 THEN [Indent] + 1 ELSE 2 END WHERE [MenuItemID] = @MenuItemID";int iResult = 0;iResult = MyStaticDBHelper.ExecuteNonQuery(conn, System.Data.CommandType.Text, strSQL, paras);return iResult;}public UserMenuItem SelectMaxOrdinal(Object conn, UserMenuItem usermenuitem){List<MyStaticDBHelper.MyDBParameter> paras = new List<MyStaticDBHelper.MyDBParameter> {new MyStaticDBHelper.MyDBParameter("@MenuID", DbType.Int32, usermenuitem.MENUID)};string strSQL = "SELECT IsNull(Max(Ordinal),0) as Ordinal FROM [UserMenuItem] WHERE [MenuID] = @MenuID";DataSet ds = null;ds = MyStaticDBHelper.ExecuteDataset(conn, System.Data.CommandType.Text, strSQL, paras);return DataMapper.MapDataTableToSingleRow<UserMenuItem>(ds.Tables[0]);}#endregion} }

這個數據訪問的代碼都是這種方式,開始準備參數。用的都是MyStaticDBHelper.MyDBParameter結構。給出參數名,參數類型,參數值和參數方向(輸入還是輸出)。然后就是一個sql語句,其中有參數。之后是根據查詢的類型,update/delete/insert的就調用db helper的ExecuteNonQuery方法,如果是select一個表的話,調用db helper的ExecuteDataset方法。再之后,就要將返回的值給轉換成對應的返回類型。如一個實體對象或者實體對象列表。這個類里的sql語句都是預先設計好的sql語句,每個sql語句都有參數,然后每個sql查詢都有一個c#方法與之對應。DataMapper.MapDataTableToSingleRow是將DataTable中第一行轉換成一個實體對象。DataMapper.MapDataTableToObjectList是將返回的DataTable轉換成實體類的列表, 即List<實體類>,這里DataMapper類采用了Reflection的方式來進行轉換實體類。雖然不是最快的。在某些情況下也可以接受。我們做過一個實例程序來對比,將DataTable轉成實體類列表,有直接賦值,Emit, Reflection, delegate, Expression tree等不同的方法,經過性能測試,直接賦值是最快的。Emit稍微比直接賦值慢,但是已經很快了。直接賦值寫代碼比較繁瑣。Emit的方法代碼稍微有點復雜,但是運行效率不錯。又比較靈活。是個相當好的方法,Emit和Expresssion Tree的方法有一些缺點,就是很難調試,萬一出現問題會很難找到問題的根源。這里是比較不同方法將DataTable轉成數據實體類的測試代碼:??http://files.cnblogs.com/mikelij/testGenerateEntity.zip, 大家可以下載了去試試,應該說這幾種方法都還不錯。這里的代碼選用了Reflection方法。因為Reflection也沒有慢得很多。Reflection方法的兼容性好。不會出問題。Emit和Express tree方法經常會遇到不兼容類型的問題。而且很難排查問題。

?數據映射的類

using System; using System.Data; using System.Configuration; using System.Collections.Generic; using System.Reflection;namespace DataAccessCommon {public class DataMapper{public static List<TType> MapDataTableToObjectList<TType>(DataTable dt) where TType : new(){List<TType> result = new List<TType>();foreach (DataRow currentRow in dt.Rows){TType ttype = new TType();for (int i = 0; i < dt.Columns.Count; i++){for (int j = 0; j < ttype.GetType().GetProperties().Length; j++){if (dt.Columns[i].ColumnName.ToUpper() == ttype.GetType().GetProperties()[j].Name.ToUpper()){ttype.GetType().GetProperties()[j].SetValue(ttype, currentRow[i], null);break;}}}result.Add(ttype);ttype = new TType();}return result;}public static TType MapDataTableToSingleRow<TType>(DataTable dt) where TType : new(){TType ttype = new TType();if (dt.Rows.Count > 0){DataRow currentRow = dt.Rows[0];for (int i = 0; i < dt.Columns.Count; i++){for (int j = 0; j < ttype.GetType().GetProperties().Length; j++){if (dt.Columns[i].ColumnName.ToUpper() == ttype.GetType().GetProperties()[j].Name.ToUpper()){ttype.GetType().GetProperties()[j].SetValue(ttype, currentRow[i], null);break;}}}}return ttype;}} }

商業類的代碼

商業類的代碼是基于我們OOA/OOD設計出的。比如一個銀行ATM的例子,其業務里有若干名詞,比如銀行戶頭,ATM機等名詞,每個名詞下又有若干屬性,比如銀行帳號,帳號所有者名字,開立日期等,ATM機有ATM機號,地理位置,所屬銀行編號,等等。圍繞著這些名詞,有相關的一些動作。比如取錢,存錢,插卡入ATM機,記錄ATM流水。等等等等。這里已經將名詞的數據屬性放到了數據實體類里。這些數據實體類里就只有那些名詞的數據屬性,沒有那些動作,即一個純數據的類。這里要提到的商業類包含了商業方法的類,這些商業方法就對應著那些動作。比如取錢,就有一個Withdraw方法對應。存錢就就一個Deposite方法對應。這兩個方法都放在一個叫BankAccount的的商業類里面。這里用的銀行的例子,說明這里所用到的設計方法。

使用Unity之類的IOC容器進行policy injection

下面就要說說IOC了,就是說我們設計一個商業類,里面有幾個商業方法。如果讓調用者直接依賴于這個商業類,那么將來有一天要改變這些商業方法時,可能就不得不同時改調用者和商業類。為了避免這種情況,我們可以從商業類提取出一個接口。這個接口只有這些動作的名字,沒有具體具體實現。然后由負責具體實現的商業類來實現這些接口。說了這些東西與IOC有什么關系呢?這樣做正是為了實現IOC打下基礎。要知道象Unity這樣的IOC容器,都是負責創建對象。它負責從接口映射到具體的商業類。當調用者需要創建一個接口的實例,接口本身是不能實例化的,容器會為調用者創建一個實現了該接口商業類的實例。

一個商業接口的例子:

using System; namespace BusinessLogic {[MyDBHandler]public interface IBLLUserMenu{int AddUserMenu(DataEntity.UserMenu usermenu);int DeleteUserMenu(DataEntity.UserMenu usermenu);DataEntity.UserMenu FindAUserMenu(DataEntity.UserMenu usermenu);System.Collections.Generic.List<DataEntity.UserMenu> GetAllUserMenu();int SelectCountUserMenu();int SelectCountWhereClauseUserMenu(DataEntity.UserMenu usermenu);System.Collections.Generic.List<DataEntity.UserMenu> SelectGroupByPrimaryKeyUserMenu();System.Collections.Generic.List<DataEntity.UserMenu> SelectMenusByApplicationID(DataEntity.UserMenu usermenu);System.Collections.Generic.List<DataEntity.UserMenu> SelectOrderByPrimaryKeyUserMenu();System.Collections.Generic.List<DataEntity.UserMenu> SelectTopUserMenu();int UpdateUserMenu(DataEntity.UserMenu usermenu);object CONNECTION { get; set; }DataEntity.UserMenu USERMENU { get; set; }System.Collections.Generic.List<DataEntity.UserMenu> USERMENU_LIST { get; set; }} }

此代碼中的MyDBHandler是一個字定義的attribute, 用于Unity來進行攔截判斷。有這個attribute就攔截,沒有就不攔截。
而相應的商業類就是這樣的:

using System; using System.Collections.Generic; using System.Data; using DataEntity; using DataAccess; using DataAccessCommon; using CommonUtil;namespace BusinessLogic {internal class BLLUserMenu : BusinessLogic.IBLLUserMenu{private readonly DataAccess.DALUserMenu dal = new DataAccess.DALUserMenu();private object conn = null;private UserMenu usermenu;private List<UserMenu> usermenus;public object CONNECTION{get{return conn;}set{conn = value;}}public UserMenu USERMENU{get{return usermenu;}set{usermenu = value;}}public List<UserMenu> USERMENU_LIST{get{return usermenus;}set{usermenus = value;}}#region business logic methodpublic int DeleteUserMenu(UserMenu usermenu){return dal.DeleteUserMenu(conn,usermenu);}public int UpdateUserMenu(UserMenu usermenu){return dal.UpdateUserMenu(conn,usermenu);}public int AddUserMenu(UserMenu usermenu){return dal.AddUserMenu(conn,usermenu);}public List<UserMenu> GetAllUserMenu(){return dal.GetAllUserMenu(conn);}public UserMenu FindAUserMenu(UserMenu usermenu){return dal.FindAUserMenu(conn,usermenu);}public System.Int32 SelectCountUserMenu(){return dal.SelectCountUserMenu(conn);}public System.Int32 SelectCountWhereClauseUserMenu(UserMenu usermenu){return dal.SelectCountWhereClauseUserMenu(conn,usermenu);}public List<UserMenu> SelectTopUserMenu(){return dal.SelectTopUserMenu(conn);}public List<UserMenu> SelectOrderByPrimaryKeyUserMenu(){return dal.SelectOrderByPrimaryKeyUserMenu(conn);}public List<UserMenu> SelectGroupByPrimaryKeyUserMenu(){return dal.SelectGroupByPrimaryKeyUserMenu(conn);}public List<UserMenu> SelectMenusByApplicationID(UserMenu usermenu){return dal.SelectMenusByApplicationID(conn, usermenu);}#endregion} }

目前這個商業類的方法都比較簡單,如果有比較復雜的,可能一個商業方法里需要調用數據訪問的方法好多個,在做一些邏輯判斷。那么這些商業方法就可以變得復雜多了。如這樣的一個商業方法:

public bool MoveUpItem(UserMenuItem usermenuitem){usermenuitem = dal.FindAUserMenuItem(conn, usermenuitem);UserMenuItem previousMenuItem = dal.SelectPreviousMenuItem(conn, usermenuitem);int iTempOrdinal = usermenuitem.Ordinal;usermenuitem.Ordinal = previousMenuItem.Ordinal;previousMenuItem.Ordinal = iTempOrdinal;dal.UpdateUserMenuItem(conn, usermenuitem);dal.UpdateUserMenuItem(conn, previousMenuItem);return true;}

Unity配置信息:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"><sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" /><namespace name="BusinessLogic" /><container name="myContainer"><extension type="Interception" /><register type="BusinessLogic.IBLLApplication, BusinessLogic" mapTo="BusinessLogic.BLLApplication, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLDomain, BusinessLogic" mapTo="BusinessLogic.BLLDomain, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLFormElement, BusinessLogic" mapTo="BusinessLogic.BLLFormElement, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLUserAccount, BusinessLogic" mapTo="BusinessLogic.BLLUserAccount, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLUserColumns, BusinessLogic" mapTo="BusinessLogic.BLLUserColumns, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLUserForm, BusinessLogic" mapTo="BusinessLogic.BLLUserForm, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLUserMenu, BusinessLogic" mapTo="BusinessLogic.BLLUserMenu, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLUserMenuItem, BusinessLogic" mapTo="BusinessLogic.BLLUserMenuItem, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLUserSession, BusinessLogic" mapTo="BusinessLogic.BLLUserSession, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><register type="BusinessLogic.IBLLUserTables, BusinessLogic" mapTo="BusinessLogic.BLLUserTables, BusinessLogic"><interceptor name="myinterceptor" type="InterfaceInterceptor" isDefaultForType="true" /><policyInjection /></register><interception><policy name="mypolicy"><callHandler name="myHandler1" type="BusinessLogic.MyDBHandler, BusinessLogic"></callHandler><matchingRule name="myrule" type="CustomAttributeMatchingRule"><constructor><param name="attributeType" type="System.Type, mscorlib"><value value="BusinessLogic.MyDBHandlerAttribute, BusinessLogic" typeConverter="BusinessLogic.GetTypeConverter, BusinessLogic" /></param><param name="inherited" type="bool"><value value="true" /></param></constructor></matchingRule></policy></interception></container></unity>

注意到這些register的節點沒有?這些節點實現了接口到具體商業類的映射。接口表示的是一個抽象。它只有方法的聲明,沒有具體實現。在調用者需要一個具體的實現了這個接口的商業類時,容器幫助我們創建這個商業類的實例,而接口到商業類的映射就是在Unity配置文件里做的。
Unity除了幫助我們實現接口到商業類的映射,還可以幫助我們實現aop. 比如log, db transaction, exception handling.

using System; using System.Data; using System.Data.Common; using System.Collections.Generic; using Microsoft.Practices.Unity.InterceptionExtension; using DataAccessCommon; using CommonUtil;namespace BusinessLogic {public class MyDBHandler : ICallHandler{private int iOrder = 0;public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext){var retvalue = getNext()(input, getNext); // call the intercepting methodif (retvalue.Exception != null){SysLog.GetInstance().LogError(retvalue.Exception);}return retvalue;}public int Order{get{return iOrder;}set{iOrder = value;}}} }

這個MyDBHandler已經在之前的Unity配置中指定了。即這句:

<callHandler name="myHandler1" type="BusinessLogic.MyDBHandler, BusinessLogic"></callHandler>

這句是去調用被攔截的方法:

retvalue = getNext()(input, getNext);

被攔截方法(即我們的商業方法)返回以后,程序就檢查retvalue.Exception有沒有出錯,有就調用logging的類來寫log。將出錯信息完整地打印出來。
自定義的attribute類:

using System; using System.Collections.Generic; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; namespace BusinessLogic {public class MyDBHandlerAttribute : HandlerAttribute{public override ICallHandler CreateHandler(IUnityContainer container){return new MyDBHandler();}} }

至于db transaction, 如果數據庫事務比較簡單,可以用TransactionScope,前面的MyDBHandler的invoke方法就替換成這樣。

using (TransactionScope ts = new TransactionScope()){var retvalue = getNext().Invoke(input, getNext);if (retvalue.Exception != null){SysLog.GetInstance().LogError(retvalue.Exception);}else{ts.Complete();}return retvalue}

Unity配置里用到的一個工具類代碼:

using System; using System.Collections.Generic; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; namespace BusinessLogic {public class GetTypeConverter : System.ComponentModel.TypeConverter{public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context,System.Globalization.CultureInfo culture,object value){return Type.GetType(value.ToString());}} }

這個類用來做類型轉換的。用來幫助Unity來找自定義的MyDBHandlerAttribute的。

商業類的調用者

為了調用商業類,我們有一個類來幫助創建相應的商業類的實例:

using System; using System.Collections.Generic; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.Configuration;namespace BusinessLogic {public static class BusinessClassCreator{public static IUnityContainer container = new UnityContainer().LoadConfiguration("myContainer");public static T GetInstance<T>(){return (T)container.Resolve(typeof(T), null);}public static object GetInstance(Type type){return container.Resolve(type, null);}} }

在調用的地方代碼這么寫:

[HttpGet]public ActionResult SaveMenuScheme(){UserMenu userMenu = new UserMenu();userMenu.MenuID = GetMenuID(this);userMenu = BusinessClassCreator.GetInstance<IBLLUserMenu>().FindAUserMenu(userMenu);short bMenuScheme = 0;bMenuScheme = (short)DesignTableController.GetID(this);userMenu.Scheme = bMenuScheme;BusinessClassCreator.GetInstance<IBLLUserMenu>().UpdateUserMenu(userMenu);return DisplayMenuList();}

這是一個在asp.net mvc中調用上述商業類的樣例代碼,首先通過BusinessClassCreator.GetInstance<IBLLUserMenu>()得到接口IBLLUserMenu對應的商業類對象,然后再調用IBLLUserMenu接口上的方法。比如此例中調用了FindUserMenu方法和UpdateUserMenu方法。每個方法的返回類型已經由接口定義好。我們只要按照這個接口的定義來使用這個接口就可以了。接口在這里的好處就是它定義了商業類的規范,所有實現此接口的商業類都符合此接口的規范。而且具體實現和接口定義是分離的。這樣我們就可以單獨改變實現接口的商業類。商業類的調用者既可以是一個asp.net mvc的程序,也可以是一個asp.net web form的,還可以是一個winform程序。

?demo代碼下載: http://dl.vmall.com/c08haaatpu, 博客園這里上傳不了。沒有辦法。只能選別處了。

總結

以上是生活随笔為你收集整理的实战分层架构的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

日韩伦理片一区二区三区 | 亚洲国产成人久久 | av短片在线观看 | 久草视频在线看 | 免费看av片网站 | 中文字幕第| 香蕉网在线观看 | 亚洲资源在线网 | 国产精品福利在线观看 | 久久久久久久久久久久久久av | 伊人国产在线播放 | 国产黄色播放 | 九九欧美视频 | 久久精品成人热国产成 | 园产精品久久久久久久7电影 | 天天鲁一鲁摸一摸爽一爽 | 久久视频免费观看 | 久草网在线观看 | 国产精品美女久久久久久久网站 | 国产精品美女久久久免费 | 看v片| 超碰97久久| 在线免费观看视频你懂的 | 亚洲久草视频 | 亚洲黄色免费电影 | www亚洲国产| 国产精品美女久久久久久久久 | 毛片.com| 91麻豆精品国产91久久久久久久久 | 综合天天| 久久免费成人网 | 欧美日韩免费一区二区三区 | 麻豆免费在线播放 | 成人av教育| 一区二区网 | 婷婷色在线播放 | 亚洲精品视频第一页 | 91九色视频| 精品国产一区二区三区久久久蜜月 | 日韩av不卡播放 | 91麻豆精品一区二区三区 | 在线观看黄污 | 黄色的网站在线 | 国产精品久久久久久妇 | 97夜夜澡人人双人人人喊 | 国产色拍| 日韩伦理片一区二区三区 | 免费看毛片在线 | 狠狠干夜夜操天天爽 | 国产黄视频在线观看 | 视频在线观看日韩 | 一本一道久久a久久综合蜜桃 | 99热精品国产一区二区在线观看 | 四虎影视成人精品 | 色婷婷亚洲精品 | 中文字幕免费播放 | 日韩大片免费观看 | 五月激情综合婷婷 | 国产一区二区久久久 | 国产剧情一区在线 | 欧美色图视频一区 | 在线电影av| 天天干夜夜擦 | 91最新网址在线观看 | 日p在线观看 | 亚洲精品国产免费 | 国产亚洲一区 | av字幕在线| 免费av在 | 欧美极度另类性三渗透 | 成人性生交大片免费看中文网站 | 91视频免费观看 | 欧美日韩高清一区二区 国产亚洲免费看 | 又黄又爽又刺激 | 国产精品久久伊人 | 久精品视频免费观看2 | 日韩一级电影在线观看 | 国产黄色资源 | 国产原创在线视频 | 欧美不卡在线 | 中文av影院| 亚洲无吗天堂 | 亚洲精选视频免费看 | 日韩精品久久久久久久电影99爱 | 日韩免费视频线观看 | 久久久精品在线观看 | 久久精品国产免费看久久精品 | 黄色免费观看网址 | 丁香婷婷激情啪啪 | 亚洲日本成人 | 视频在线观看入口黄最新永久免费国产 | 最新中文字幕 | 在线最新av | 97超级碰碰碰视频在线观看 | 天天干天天射天天插 | 久久久久久久久久久网 | 欧美日韩国产在线 | 麻花天美星空视频 | 深爱激情五月综合 | 午夜av色| 国产1区2区3区精品美女 | 69精品| 爱射综合 | 欧美狠狠色 | 成人动漫视频在线 | 免费观看的黄色 | 午夜av影院 | www.啪啪.com| 婷婷五月在线视频 | 国产裸体无遮挡 | 九九一级片 | 亚洲 欧美 另类人妖 | 欧美性生交大片免网 | 怡红院久久| 日韩在线观看视频在线 | 操操爽 | 69久久久久久久 | 国产麻豆视频在线观看 | 精品乱码一区二区三四区 | www五月天婷婷 | 午夜精品99久久免费 | 日韩av一区二区三区四区 | 国产麻豆果冻传媒在线观看 | 久草手机视频 | 美女视频黄网站 | 免费看三级黄色片 | 日韩高清不卡一区二区三区 | 黄色片网站免费 | 国产视频精品久久 | 精品亚洲免费视频 | 亚洲精品国产综合99久久夜夜嗨 | 婷婷色婷婷| 亚洲一区视频免费观看 | 午夜免费在线观看 | 日韩av手机在线看 | 欧美日韩国产精品一区 | 日批视频在线播放 | 精品免费久久久久久 | 国产成人精品一区二区 | 久久精品爱爱视频 | 日韩高清一二三区 | 国产在线视频在线观看 | 天天干国产 | 久久久2o19精品 | 婷婷 综合 色 | 黄色免费看片网站 | 久久精品一二三区 | 久久午夜羞羞影院 | 成人h电影在线观看 | 九九亚洲视频 | 天天草天天干天天 | 国产精品福利视频 | 欧美精品三级 | 国产精品一区久久久久 | 成人av免费| 黄色最新网址 | 日韩欧美网址 | 麻花传媒mv免费观看 | 人人玩人人添人人 | 国产一级二级在线播放 | 91精品综合在线观看 | 色片网站在线观看 | 在线观看视频99 | 精品国产乱子伦一区二区 | 在线免费黄色 | 91成人在线视频 | 99久久久国产精品免费观看 | 国产精品一区二区三区免费视频 | 超碰人人在线 | 欧美一级片播放 | 久久最新视频 | 久久久久97国产 | 日韩91在线| 毛片.com| 国产综合激情 | 午夜精品三区 | 午夜三级福利 | 亚洲天天综合 | 久久夜色精品国产欧美乱极品 | 欧美国产三区 | 亚洲h视频在线 | 国产精品123 | 91视频在线免费下载 | 中文字幕av日韩 | 日韩免费福利 | 久久96国产精品久久99软件 | 天天干,天天射,天天操,天天摸 | 国产乱对白刺激视频在线观看女王 | 国产精品18久久久久久久久久久久 | 久久精品成人欧美大片古装 | 亚洲视频中文 | 久久av观看 | 日韩啪视频 | 97国产电影 | 日韩精品一区二区三区免费观看 | 国产精品久久久久国产精品日日 | 三级黄色大片在线观看 | 最新成人av | 依人成人综合网 | 国产九色91 | 久久久久久蜜桃一区二区 | av日韩国产 | 国产亚洲精品久久19p | 在线欧美小视频 | 日韩手机在线观看 | 国产视频一区二区在线播放 | 亚洲精品视频网址 | 午夜视频在线观看一区二区三区 | 91色亚洲 | 国产亚洲精品久久久久久移动网络 | 91麻豆精品一区二区三区 | 91在线播放综合 | 在线韩国电影免费观影完整版 | 国产免费小视频 | 蜜桃传媒一区二区 | 激情伊人五月天久久综合 | 天天做天天射 | 成人国产一区 | 一区二区视频网站 | 日韩av电影一区 | 91精品国产麻豆国产自产影视 | 五月婷婷网站 | 在线观看日韩精品视频 | 久久免费视频观看 | 国产精品一区二区久久久 | 韩国三级一区 | 看片的网址 | 久久国产福利 | 国产一区二区综合 | 欧美福利网址 | 国产视频一二区 | 91精品国产乱码在线观看 | 国产涩涩在线观看 | 狂野欧美激情性xxxx欧美 | 99久高清在线观看视频99精品热在线观看视频 | 日本巨乳在线 | 蜜臀av免费一区二区三区 | 91成人精品一区在线播放 | 亚洲电影黄色 | 99tvdz@gmail.com| 成片免费观看视频999 | 国产一区二区三区高清播放 | 91视频免费网址 | 在线看一级片 | 亚洲综合视频在线 | 久久国产高清视频 | 日日夜夜操av | 欧美日韩观看 | 亚洲精品乱码久久久久久写真 | 日韩欧美xxxx| 日韩视频免费在线 | 成人观看 | 麻豆国产精品视频 | 9在线观看免费高清完整版 玖玖爱免费视频 | 夜夜躁狠狠燥 | 在线看一区二区 | 天堂素人在线 | 2019中文 | 欧美激情综合五月色丁香小说 | 99精彩视频在线观看免费 | 国产精品自产拍在线观看中文 | 青青河边草观看完整版高清 | 精品久久久久久综合日本 | 2023亚洲精品国偷拍自产在线 | 人人爱人人舔 | 婷色在线| 久久精品视频中文字幕 | 久久久久久久网站 | 丁香视频免费观看 | 久爱精品在线 | 99高清视频有精品视频 | 国内久久 | 成人性生爱a∨ | 久精品视频在线观看 | 精品国产视频在线观看 | 色婷婷丁香 | 97精品国产97久久久久久粉红 | 午夜久久影视 | 狠狠狠色丁香婷婷综合激情 | 99久久精品免费看国产麻豆 | av久久在线 | www视频在线播放 | 91桃色在线观看视频 | 日韩专区在线 | 在线视频一二三 | 香蕉视频在线免费 | 国产+日韩欧美 | 色综合久久88色综合天天 | 国产又粗又长又硬免费视频 | 在线观看一区视频 | 五月婷婷av| 亚洲精品tv久久久久久久久久 | 免费在线国产精品 | 97色噜噜| 亚洲成a人片77777kkkk1在线观看 | av福利第一导航 | 青青河边草观看完整版高清 | 91精品免费视频 | 日本xxxx.com| 成人影片在线播放 | 天天干天天干天天 | 国产一级视屏 | 欧美日韩国产色综合一二三四 | 91久久久久久国产精品 | 日韩超碰 | 国产一区福利在线 | 999国内精品永久免费视频 | 一级黄色片在线免费看 | 免费亚洲婷婷 | 日韩激情在线视频 | 婷婷久操| 精品高清美女精品国产区 | 97在线影院 | 中文字幕一二三区 | 99九九99九九九视频精品 | 欧美狠狠色 | 日韩成片 | 成年人免费电影在线观看 | av在线a | 在线播放精品一区二区三区 | 久久国产精品99久久久久久丝袜 | 国产午夜在线 | 国产成人综合精品 | 波多野结衣理论片 | 国产一级在线看 | 日本精品在线看 | 欧美一级性视频 | 久久久视频在线 | 在线免费观看不卡av | 精品一区二区亚洲 | 亚洲 欧美 另类人妖 | 黄色精品一区二区 | 在线国产激情视频 | 精品99免费视频 | 国产精品对白一区二区三区 | h视频在线看| 久久激情五月激情 | 日韩高清毛片 | 日韩欧美精品一区二区 | a黄色片在线观看 | 成人黄色电影在线 | 丁香婷婷色月天 | 成人av一区二区兰花在线播放 | 亚洲蜜桃在线 | 精品国产一区二区三区蜜臀 | 久久久国产一区二区三区四区小说 | 在线播放国产精品 | 国语精品久久 | 欧美精品久久久久久 | 欧美精品一级视频 | 中文字幕亚洲精品日韩 | www色com | 国产不卡av在线 | 久久国产成人午夜av影院宅 | 中文字幕高清 | 很污的网站| 日韩视频免费观看高清 | 久久久久免费视频 | 久久久久久视频 | 中文字幕国产一区二区 | 91久久一区二区 | 不卡av电影在线观看 | 香蕉影院在线 | 波多野结衣电影一区 | 欧美久久99 | 美女黄频在线观看 | 午夜精品av| 国产资源网 | 久久九九久久 | 日韩欧美高清在线观看 | 日本黄色免费观看 | 99精品在这里| 国产精品一区免费看8c0m | 久久9视频| 在线观看av免费 | 狠狠色综合欧美激情 | 97av视频| 99综合视频 | 国产视频一区精品 | 久久一级片| www.888.av| 亚洲午夜精品久久久久久久久久久久 | 九九精品在线观看 | 久久不卡日韩美女 | 综合激情网... | 99精品视频免费在线观看 | 五月综合色 | 一性一交视频 | 精品久久久久久亚洲综合网站 | 久久久久久视频 | 天天综合天天做天天综合 | 久久婷婷色 | 黄色一级在线免费观看 | 91.dizhi永久地址最新 | 三级大片网站 | 五月激情姐姐 | 成人影音av| 日韩专区在线播放 | 国产精品专区在线 | 久久精品人 | 天天色天天干天天 | 久久国产区 | 精品国精品自拍自在线 | 视频在线播放国产 | 精品在线视频观看 | 久久久久精 | 又黄又刺激又爽的视频 | 久久不射电影网 | 久久久久久看片 | 不卡的av| 区一区二区三在线观看 | 蜜臀久久99静品久久久久久 | 91精品国产九九九久久久亚洲 | 免费色网 | 中文字幕 91 | 国产精品成人免费精品自在线观看 | 在线播放你懂 | 狠狠狠狠狠操 | 91精品国产电影 | 97国产超碰在线 | 一级电影免费在线观看 | 欧美精品一区在线发布 | 久久一本综合 | 超碰在线公开 | 亚洲欧洲精品视频 | 91丨九色丨高潮丰满 | 深夜福利视频在线观看 | 久久久高清视频 | 国产亚洲一区二区在线观看 | 中文字幕频道 | www久草| 欧美激情精品久久久 | 日韩欧美视频免费观看 | 精品国产伦一区二区三区免费 | 国产一二区免费视频 | 亚洲午夜精品福利 | 伊人干综合 | 久久久久免费视频 | 91亚洲欧美 | 国产裸体永久免费视频网站 | 国产在线视频导航 | av片免费播放| 国产不卡网站 | www色片 | 欧美一区二区在线看 | 色视频成人在线观看免 | 在线免费观看的av网站 | 中文字幕中文字幕 | 狠狠色伊人亚洲综合成人 | 欧美日视频 | 国产黄在线看 | 日本天天色 | 国产黄色视| 日本中文不卡 | 国产视频二区三区 | 精品国产不卡 | 国产在线观看地址 | 亚洲精品乱码久久久一二三 | 九九九九热精品免费视频点播观看 | 久久久久 | 久久久www成人免费精品张筱雨 | 国内精品久久久久久久影视简单 | 热久久国产精品 | 久操中文字幕在线观看 | 日日干 天天干 | 激情综合色播五月 | 国产精品美 | 久草在线视频精品 | 久久综合久久综合久久综合 | 久热超碰| 欧美做受xxx | 亚洲无吗av | 亚洲天天干 | 色综合久久精品 | 成人在线观看资源 | 亚洲精选视频免费看 | 国产黄色成人 | 久久男人中文字幕资源站 | 亚洲成人精品 | 欧美精品在线一区二区 | 色综合亚洲精品激情狠狠 | 国产福利一区二区三区在线观看 | 欧美成人中文字幕 | 精品在线免费观看 | 亚洲资源网| 久久人人爽人人爽人人片av软件 | 欧美一级性| 日韩精品一区在线观看 | 亚洲精品视频国产 | 欧美网站黄色 | 国内精品久久久久影院日本资源 | 999久久久国产精品 高清av免费观看 | 免费观看丰满少妇做爰 | 日韩欧美视频在线观看免费 | 精品亚洲一区二区 | 最新国产福利 | 午夜精品视频一区 | 国产精品99久久久久久久久久久久 | 久久久精品 一区二区三区 国产99视频在线观看 | 九九免费在线观看视频 | 天天天色综合 | 亚洲精品中文在线 | 国际精品久久久久 | 黄色免费av | 狠狠色丁香婷婷综合橹88 | 99久热在线精品视频观看 | 欧美成人一二区 | 欧美日韩亚洲第一 | 色综合久久综合网 | 国产在线精品一区二区 | 爱情影院aqdy鲁丝片二区 | 亚洲精品1234区 | 天天综合天天做天天综合 | 国产精品一区二区三区在线 | 日本不卡123| 国产精品黑丝在线观看 | 久久精品看| 久久综合欧美 | 久久狠狠一本精品综合网 | 91mv.cool在线观看 | 麻豆免费观看视频 | 中文字幕中文字幕在线中文字幕三区 | 开心激情五月婷婷 | 91精品入口| 国产一区在线免费观看 | 综合网欧美 | 国产69精品久久久久久 | 亚洲aⅴ乱码精品成人区 | 久久99热久久99精品 | 91精品免费 | 91九色网站 | 亚洲人视频在线 | 国产裸体无遮挡 | 亚洲黄色成人网 | 久久99精品热在线观看 | 天天艹 | 亚洲有 在线 | 91中文字幕一区 | 国产视频在线免费观看 | av丁香| 99r在线视频| 精品国产免费人成在线观看 | 国产精品久久久av久久久 | 97在线免费观看 | 免费网站在线观看成人 | av在线免费观看不卡 | 中文字幕亚洲国产 | 日日干干 | 国产成人精品久久亚洲高清不卡 | 成年人黄色免费视频 | 精品国产精品一区二区夜夜嗨 | 久久成人国产精品免费软件 | 久久精品综合网 | 麻豆网站免费观看 | 在线观看免费 | www.久久免费 | 免费av片在线| 日日日天天天 | 四虎精品成人免费网站 | 91麻豆操 | 天天操天天爱天天干 | 日韩手机视频 | 免费在线国产黄色 | 欧美老人xxxx18| 久久久久久国产精品 | av免费看av| 国产91aaa | 九九热免费精品视频 | 偷拍区另类综合在线 | 欧美一级乱黄 | 少妇搡bbbb搡bbb搡aa | 国产伦精品一区二区三区照片91 | 国产不卡免费av | 午夜精品久久久久99热app | 很黄很污的视频网站 | 国产精品视频专区 | 高清国产午夜精品久久久久久 | 亚洲男人天堂a | 欧美久久久久久久久久久 | 精品国产一区二区三区久久久久久 | 国产色婷婷 | 经典三级一区 | 中文在线字幕免费观 | 91大神精品视频 | 国产91影院| 亚洲视频专区在线 | 久久精品免费电影 | 一区二区三区日韩视频在线观看 | 日韩精品资源 | 国产精品日韩久久久久 | 国产色黄网站 | 久久国产精品久久精品国产演员表 | 午夜精品视频福利 | 久久99深爱久久99精品 | 日韩91在线 | 97电影在线看视频 | 69亚洲精品| 成人免费观看网址 | 在线a人片免费观看视频 | 欧美一区免费在线观看 | 国产精品理论视频 | 激情影音先锋 | 亚洲欧美视频 | 日韩天堂在线观看 | 色噜噜在线观看视频 | 狠狠久久 | 婷婷夜夜| 国产视频精品在线 | 99视频99 | 91亚洲网| 97视频总站 | a在线播放 | 亚洲三级在线免费观看 | 中文字幕婷婷 | 久久亚洲私人国产精品va | 精品国产亚洲在线 | 日韩欧美电影在线 | 亚洲jizzjizz日本少妇 | 日韩极品在线 | 国产精品久久久久久久久久三级 | 成人av影视在线 | 香蕉视频色 | 国产亚洲精品久久19p | 果冻av在线 | 在线观看亚洲免费视频 | 国产精品视频你懂的 | 精品久久久久久久久久久院品网 | 日韩精品视频免费在线观看 | av大全在线观看 | 黄色福利网站 | 91插插影库 | 在线视频婷婷 | 欧美日韩观看 | 亚洲精品一区二区精华 | 国产一区二区电影在线观看 | 国产日韩中文字幕在线 | 中文一二区 | 91亚洲在线观看 | 国产福利久久 | av资源免费在线观看 | 日本三级中文字幕在线观看 | 亚洲91精品在线观看 | japanesexxxhd奶水 国产一区二区在线免费观看 | 成人免费亚洲 | 亚洲国产精品成人av | 亚洲激情影院 | 亚洲天堂网视频 | 五月天伊人网 | 久久亚洲福利视频 | 日韩视频一二三区 | 色福利网 | 久久精品一区二区三区中文字幕 | 欧美三级在线播放 | 亚洲 欧美 变态 国产 另类 | 韩国一区二区三区在线观看 | 91精品入口 | 国产精品久久久久久吹潮天美传媒 | 国产成人精品久久亚洲高清不卡 | 美女视频黄是免费的 | 国产精品99久久久久久宅男 | 久草在线看片 | 亚洲精品国| 操操综合 | 视频一区二区精品 | 久久久综合电影 | 69国产精品视频 | 一级性生活片 | 91在线产啪| 色国产在线 | 伊人网综合在线观看 | 国产在线资源 | 四虎永久网站 | 国产精品一区二区三区四 | 日韩电影中文字幕 | 欧美一区二区三区在线视频观看 | 丁香六月婷 | 久久成人国产精品免费软件 | 日韩免费中文字幕 | 99久久免费看 | 久久人人爽人人片av | 99久久久国产免费 | 五月天久久婷婷 | 免费a网 | 亚洲国产三级在线 | 久久久受www免费人成 | 日韩在线观看一区二区 | 亚洲国产欧洲综合997久久, | 91亚洲精品在线 | 在线观看91 | 久久狠狠一本精品综合网 | 国产色婷婷精品综合在线手机播放 | 中文字幕一区二区三区乱码在线 | 欧美a在线看 | www.五月天婷婷 | 亚洲激情六月 | 国产蜜臀av | 深夜免费小视频 | 亚洲免费婷婷 | 丁香花在线观看免费完整版视频 | 久久久在线观看 | 亚洲三级毛片 | 国产乱码精品一区二区蜜臀 | 欧美日韩在线看 | 亚洲一二三久久 | 免费下载高清毛片 | 中文字幕日韩国产 | 欧美视频在线观看免费网址 | 丝袜美女在线观看 | 久久久久激情视频 | 亚洲精品黄色在线观看 | 久久久久久久久久久久亚洲 | 欧美va日韩va| 免费精品视频在线 | 国产视频一区精品 | 成人国产网站 | 天天操天天射天天 | 久久久久国产免费免费 | 欧美一二三区在线观看 | 91精品视频在线观看免费 | 91热视频在线观看 | 青青河边草免费视频 | 久久久久亚洲最大xxxx | www99久久 | 黄色综合 | 在线看一区 | 又黄又爽的视频在线观看网站 | 国产精品一区二区在线免费观看 | 精品中文字幕视频 | 永久免费看av | 在线免费观看视频 | 在线观看视频99 | 一区二区三区在线看 | 精品欧美一区二区三区久久久 | 四虎在线永久免费观看 | 免费日韩av电影 | 91麻豆免费版 | av高清影院 | 国产高清视频免费在线观看 | 亚洲国产大片 | 日韩在线观看 | 日韩区视频 | 国产精品av久久久久久无 | 日韩最新理论电影 | 久久久精品久久日韩一区综合 | 久草在线资源视频 | 天天操天天玩 | 三级av免费看 | 99电影| 国产福利精品在线观看 | 久久久www | 91精品免费视频 | 正在播放国产91 | 91久久久久久久 | 国产一级免费在线观看 | 午夜精品久久久久久久99无限制 | 99热九九这里只有精品10 | 人人添人人澡人人澡人人人爽 | 久久国产亚洲精品 | 国产亚洲精品电影 | 欧美成人中文字幕 | 久久天堂网站 | 国产午夜精品一区二区三区嫩草 | 九九热在线观看视频 | 亚洲三级在线免费观看 | 久久精品一二三区 | 国产精品久久精品 | 成人午夜电影网 | 亚洲免费成人av电影 | 久久久久久久久久伊人 | 又污又黄网站 | 成人黄色电影在线观看 | 亚洲第一色| 亚洲精品网站在线 | 日韩久久视频 | 亚洲精品国偷拍自产在线观看蜜桃 | 午夜精品久久久久久久99 | 久久久国产精品一区二区三区 | 国产综合在线视频 | 最新超碰在线 | 亚洲永久国产精品 | 国产精品久久久777 成人手机在线视频 | 色久网 | 免费国产亚洲视频 | 日韩成人精品一区二区 | av在线免费观看黄 | 欧美va天堂va视频va在线 | 草久在线观看 | 玖玖在线看| 777视频在线观看 | 国产精品久久伊人 | 国产高清不卡一区二区三区 | 亚洲欧美日韩国产一区二区三区 | 日本久久久久久科技有限公司 | 天天干天天拍 | 毛片视频网址 | 中文字幕有码在线观看 | 国产高清免费视频 | 欧美精品久久久久久久久久丰满 | 最新日韩电影 | 久久精品中文字幕 | 日韩在线视频看看 | 国产亚洲精品中文字幕 | 国产成人一二三 | 欧美视频在线观看免费网址 | 日韩av在线看 | 久久久久久99精品 | 国产精品一区二区吃奶在线观看 | 久久九九九九 | 国产99免费视频 | 韩国av免费在线 | 欧美一级片免费在线观看 | 一区二区三区在线免费观看 | 国产小视频在线免费观看视频 | 五月在线 | 久久毛片高清国产 | 日韩亚洲精品电影 | 国产精品久久99综合免费观看尤物 | 97国产小视频 | 五月综合在线观看 | 日韩在线免费电影 | 色噜噜狠狠狠狠色综合 | 久久久午夜电影 | 国产黄色片久久久 | www.婷婷色| 国产在线国偷精品产拍 | 亚洲精品视频中文字幕 | 亚洲人久久| 久久久一本精品99久久精品 | 久久久久久久久毛片精品 | av东方在线 | 91精品久久久久久久久 | 最近中文字幕完整高清 | 国产精品视频免费看 | 国产精品视频区 | 91九色蝌蚪视频在线 | 99精品久久只有精品 | 人人精久 | 天天综合操 | 亚洲资源在线 | 久久久久亚洲a | 色九九影院 | 久久国产精品视频观看 | 国产麻豆果冻传媒在线观看 | 黄色软件视频大全免费下载 | 亚洲一级黄色 | 狠狠干网 | 国产精品女 | 免费特级黄色片 | 91av原创| 在线天堂v| 国产乱码精品一区二区三区介绍 | 精品在线小视频 | 亚洲美女精品视频 | 在线a亚洲视频播放在线观看 | 久久免费看毛片 | 91在线超碰 | 91精品网站在线观看 | 免费在线观看黄网站 | 精品久久久久一区二区国产 | 亚洲高清在线 | 亚洲aⅴ乱码精品成人区 | 精壮的侍卫呻吟h | 日韩网站在线 | 波多野结衣一区三区 | 日韩高清免费观看 | 亚洲国产免费网站 | 韩国av在线 | 日本黄区免费视频观看 | 国产亚洲精品精品精品 | 精品电影一区 | 国偷自产视频一区二区久 | 国产精品影音先锋 | 精品国产一区二区三区男人吃奶 | 夜夜操天天操 | 久久免费99精品久久久久久 | 中文字幕中文字幕中文字幕 | 日韩 在线 | 免费a网址| 亚洲激情电影在线 | 久久五月精品 | 亚洲精品中文字幕视频 | 免费看毛片网站 | 久久深夜 | 成年人视频在线免费 | 日韩欧美在线综合网 | 日韩在线播放欧美字幕 | 热99久久精品 | 久久免费视频2 | 91久久偷偷做嫩草影院 | 国产美女视频 | 久久精品免费播放 | 日韩在线中文字幕视频 | 色播亚洲婷婷 | 午夜黄色影院 | 欧美性受极品xxxx喷水 | 国产精品第十页 | 国产视频手机在线 | 久草久视频 | 免费看黄色大全 | 亚洲国产精品一区二区久久hs | 欧美伦理一区二区三区 | 国产专区一 | 免费观看v片在线观看 | 国产视频九色蝌蚪 | 美女久久久 | 天天色综合天天 | 婷婷色婷婷| 国产精品久久毛片 | 一区二区不卡在线观看 | 欧美日韩在线精品一区二区 | 丰满少妇在线观看资源站 | 久久久影院一区二区三区 | 日本黄色免费在线 | av免费看电影 | 人人舔人人爱 | 久久综合成人网 | 国产欧美久久久精品影院 | 特级毛片在线免费观看 | 国产高清99| 黄色av一区二区 | 久久男人中文字幕资源站 | 日韩一区二区三区免费视频 | 国产精品一区二区av | 麻豆传媒精品 | 国产一区二区午夜 | 伊人久久av | 中文字幕在线观看视频一区 | 成人av在线直播 | 黄色三级在线 | 欧美少妇18p | 日本狠狠色 | 久久免费的视频 | 亚洲福利精品 | 国产对白av| 欧美日韩精品在线一区二区 | 97视频久久久 | 亚洲国产精品人久久电影 | 久久99视频 | a视频在线看| 综合网中文字幕 | 亚洲国产精品成人va在线观看 | 伊人国产视频 | 欧美激情va永久在线播放 | 啪啪免费观看网站 | 黄a网| 日韩精品91偷拍在线观看 | 深夜免费福利视频 | 国产一线二线三线性视频 | 欧美久草视频 | 激情五月婷婷综合网 | 美女免费视频黄 | 激情久久五月天 | 天天操天天色天天射 | 五月天国产精品 | 欧美激情精品久久久久久免费 | 久久久久免费观看 | 日本精品一 | 精品国产一区二区三区久久影院 | 日韩精品一区二区不卡 | 国产精品第10页 | 99精品免费 | 五月婷婷在线视频 | 九九热免费观看 | 开心激情网五月天 | 久久国产香蕉视频 | 狠狠狠狠狠狠干 | 国产探花视频在线播放 | 黄网站色欧美视频 | 亚洲视频网站在线观看 | 国产亚洲精品无 | 在线国产高清 | 五月天激情视频在线观看 | 天堂在线v | 在线小视频 | 字幕网av | 天天干天天怕 | 99精品欧美一区二区蜜桃免费 | 国产在线看一区 | 亚洲午夜激情网 | 五月婷婷丁香网 | 国产精品自产拍在线观看 | 国产精品18p | 日日干精品| 国产色爽 | av中文在线 | 久久精品三级 | 国产资源免费在线观看 | 色狠狠综合 | 国产精品一区免费看8c0m | 九九九免费视频 | 国产精品第一视频 | 天天操夜夜曰 | 久草免费手机视频 | 久久精品免费观看 | 日日夜夜精品免费观看 | 在线播放亚洲激情 | 麻豆精品传媒视频 | 男女拍拍免费视频 |