萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 編程語言綜合 >> ado.net快速上手疑問及解答

ado.net快速上手疑問及解答

 一、代碼中的問題

  1、偽SqlMapper的基類為什麼用抽象類BaseSqlMapper而不用接口?

  答:樓豬也知道在IBatis下的SqlMapper的基類就是一個接口ISqlMapper,但是樓豬寫代碼的時候,發現泛型約束在抽象基類裡寫一次,在SqlMapper下就不要再寫了,而用接口就必須寫兩遍約束。呵呵,一時偷懶的後果,沒有深刻意識到“針對接口編程”這一條常識,提出這個問題的童鞋明顯可以看出技高樓豬一籌啊,,哈哈,樓豬吸取這個教訓了,本文最後的demo樓豬將BaseSqlMapper統一換成了ISqlMapper接口,請留意。

  2、在前台頁面裡面寫SQL語句太多,是不是不太好?

  這個問題也很好。在實際的項目中,SQL語句通常都寫在具體的Dao文件中,比如前文demo中提到的PersonDao類。我們在添加一個Person的時候,示例中是通過view plaincopy to clipboardPRint?

  public int Insert(string sqlInsert)

  public int Insert(string sqlInsert)

  這種形式的方法執行插入的,但是在實際項目中的時候,我們通常都會寫view plaincopy to clipboardprint?

  public int Insert(Person model)

  public int Insert(Person model)

  這種類型的方法執行數據庫插入操作。所以在前台(表現層)寫SQL語句其實是不合理的。再次多多感謝指出代碼問題的童鞋們。如果已經對某些新手造成某些誤導,樓豬在這裡要深刻反省和檢討(demo寫的明顯有點隨意和偷懶),在這裡,樓豬鄭重提醒,SQL語句的位置請不要模仿demo中這種糟糕的寫法,樓豬也是過來人,因為使用Batis.net的時候都是放在Dal層xml下的,請務必重視起來。

  二、疑問(直接摘錄郵件內容)

  1、“數據庫切換貌似沒有是吧.怎樣切換MSSQL。ACC,XML等等呢”?

  答:這個應該是說源碼對多種數據庫的支持問題。哦,樓豬還沒有實現。看源碼,Sql Server簡單的基本的CRUD功能已經支持了。如果要擴展支持其他數據庫,模仿SqlServer類裡的具體實現即可。樓豬的機器環境上沒有安裝Oracle或者MySQL等數據庫,所以寫完了也不好測試。您如果條件具備,自己可以試著完成它。至於說數據庫的切換,理想狀態的實現莫過於最經典的抽象工廠模式,呵呵,配置文件配合反射就行了。但是樓豬建議您簡單使用偽SqlMapper進行數據庫類型切換。具體操作,其實只要在配置文件appsetting中加一個數據庫類型節點sqlType,配合類裡的常用數據庫類型的枚舉即可。

  <appSettings>

  <add key="db_timeOut" value="5000"/>

  <!--數據庫類型 0 SqlServer 1 Orcale 2 MySql-->

  <add key="sqlType" value="0"/>

  </appSettings>

  枚舉如下:

  代碼

  namespace AdoNetDataaccess.Mapper

  {

  public enum SqlEnum

  {

  Default = 0,

  SQLServer = 0,

  Oracle = 1,

  MySql = 1

  }

  }

  然後,就是一些實例化SqlMapper的過程判斷了,將數據庫切換的問題完全轉移到實例化SqlMapper上來:

  代碼

  using System;

  using System.Collections.Generic;

  using System.Configuration;

  namespace AdoNetDataAccess.Mapper

  {

  using AdoNetDataAccess.Core.Contract;

  using AdoNetDataAccess.Core.Implement;

  #region enum

  public enum SqlEnum

  {

  Default = 0,

  SQLServer = 0,

  Oracle = 1,

  MySql = 1

  }

  #endregion

  public sealed class MapperUtill

  {

  #region fields

  public static string currentSqlKey = "sqlConn";

  public static int cmdTimeOut = 15;

  private static int sqlType = 0;//數據庫類型 0 SqlServer 1 Orcale 2 MySql

  private static readonly object objSync = new object();

  private static readonly IDictionary<string, ISqlMapper> dictMappers = new Dictionary<string, ISqlMapper>();

  #endregion

  #region constructor and methods

  private MapperUtill()

  {

  }

  static MapperUtill()

  {

  try

  {

  cmdTimeOut = int.Parse(ConfigurationManager.AppSettings["db_timeOut"]);

  }

  catch

  {

  cmdTimeOut = 15;

  }

  try

  {

  sqlType = int.Parse(ConfigurationManager.AppSettings["sqlType"]);

  }

  catch (Exception ex)

  {

  throw ex;

  }

  //實例化SqlDbMapper

  for (int i = 0; i < ConfigurationManager.ConnectionStrings.Count; i++)

  {

  string key = ConfigurationManager.ConnectionStrings[i].Name;

  string value = ConfigurationManager.ConnectionStrings[i].ConnectionString;

  CreateMapper(key, value, cmdTimeOut);

  }

  }

 

  public static ISqlMapper GetSqlMapper(string key)

  {

  return MapperUtill.GetMapper(key);

  }

  public static ISqlMapper GetCurrentSqlMapper()

  {

  return MapperUtill.GetMapper(currentSqlKey);

  }

  public static void CreateMapper(string connKey, string sqlConStr, int connTimeOut)

  {

  IDbOperation operation = null;

  switch (sqlType)

  {

  default:

  case 0:

  operation = new SqlServer(sqlConStr, connTimeOut);

  break;

  case 1:

  //operation = new Orcale(sqlConStr, connTimeOut);//Orcale 未實現

  break;

  case 2:

  //operation = new MySql(sqlConStr, connTimeOut);//MySql 也沒有實現呢

  break;

  }

  if (operation == null)

  {

  throw new Exception("您配置的數據庫類型有可能那啥出問題了");

  }

  SqlMapper mapper = new SqlMapper(operation);

  dictMappers.Add(connKey.ToUpper().Trim(), mapper);//不區分大小寫

  }

  public static ISqlMapper GetMapper(string sqlConKey)

  {

  if (string.IsNullOrEmpty(sqlConKey))

  {

  throw new Exception("數據庫連接字符串主鍵為空!");

  }

  sqlConKey = sqlConKey.ToUpper();//不區分大小寫

  ISqlMapper mapper = null;

  if (dictMappers.ContainsKey(sqlConKey))

  {

  mapper = dictMappers[sqlConKey];

  }

  else

  {

  throw new Exception(string.Format("沒有{0}所對應的數據庫連接", sqlConKey));

  }

  return mapper;

  }

  /// <summary>

  /// 釋放所有

  /// </summary>

  public void Release()

  {

  foreach (KeyValuePair<string, ISqlMapper> kv in dictMappers)

  {

  SqlMapper mapper = kv.Value as SqlMapper;

  if (mapper == null)

  {

  continue;

  }

  mapper.CurrentDbOperation.CloseConnection();

  }

  dictMappers.Clear();

  }

  #endregion

  }

  }

  必須要注意,這裡的數據庫切換方式不是絕對的,您可以按照自己喜歡的習慣的其他方式編程完成切換,樓豬這裡只是拋磚而已。

  2、“我對ORM不熟悉,想問下您的這個ORM到底是節省了哪部分工作? 我看裡面有大量的反射,這樣是不是非常影響效率?”

  首先,樓豬對ORM也不太熟悉。現在實現的這個嚴格來說也根本談不上算是ORM,但是有樓豬自己使用過的兩個ORM的影子。

  其次,當前實現的東東不是為了節省哪部分工作而設計的,樓豬的初衷是重讀ado.net經典紅皮書而做的復習筆記。

  第三,反射相對於沒有使用反射,當然非常影響效率。需要說明的是,要不要使用反射應該根據實際的項目需要。根據樓豬個人開發經驗,對於大多數程序員要實現的簡單的常見的前後台mis系統,在保證基本需求的情況下,客戶如果對效率沒有意見,用用沒有太大關系,大部分工作就交給服務器完成去吧,程序員不用做太多工作。但是對於訪問頻繁的大型網站,實時系統或者應對大數據量操作的系統等等,建議不要使用反射,而且可能要重點花精力在數據“裝潢”上面。

  最後,如果有童鞋對ORM感興趣,不妨在網上搜搜大牛們的作

copyright © 萬盛學電腦網 all rights reserved