中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

LINQ To SQL和ORM怎么理解

發布時間:2021-12-02 09:32:21 來源:億速云 閱讀:165 作者:iii 欄目:編程語言

這篇文章主要講解了“LINQ To SQL和ORM怎么理解”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“LINQ To SQL和ORM怎么理解”吧!

LINQ To SQL和ORM的理解1、

沒有LINQ的源代碼,不知道清楚中間的數據是如何處理的,特別是緩存是如何處理的。

LINQ To SQL和ORM的理解2、

用LINQ翻譯到存儲過程/Sql語句效率很低的,對于復雜的對效率有一定的要求的,還是要寫存儲過程。而且翻譯出來的存儲過程/Sql語句的怎么緩存,第二次執行的時候還要重新翻譯,不能很好的利用緩存。

LINQ To SQL和ORM的理解3、工具的支持。

這一點是非常重要。如果沒有有力工具的支持,用ORM簡直就是惡夢。LINQ的工具支持總的來說,現在在VS2008里的支持我感覺還不是很友好。至少有一點,我們通常在表的備注里面寫下這個字段的注釋,很多情況下對應到界面上就是這個字段的抬頭,這個工具不能直接生成到項目里去,因為我們不能控制,再者,現在的項目都不是由一個人完成,如果一個類有幾十個字段,很難記住解釋,自己的工具可以加入注釋,方便開發。

LINQ To SQL和ORM的理解4、與業務層的綜合。

通常ORM映射就是把對象與關系表之間形成映射關系,映射的目標是為了方便業務層的邏輯處理,如果不能與業務層無縫的結合起來,那么對于項目的開發,也未必有多少好處。至少在的ORM里面,與的我業務層可以非常友好的集成在一起。

LINQ To SQL和ORM的理解5、多數據源的支持。

對于我來說,這點也是非常關鍵的。我說的多數據源是指一個項目里面,有多個數據庫,比如:基礎數據、客戶管理、業務運作、權限管理等,這些都是相對獨立的模塊,開發的時候,可以把這幾個作為單獨的項目開發,各自有自己獨立的數據庫,而且在多個項目里面,這些模塊都是非常相似,像權限模塊基本上是通用的,沒有必要再重復開發。如果能夠做到數據庫層分離,則新項目開發的時候,可以達到更快的速度。當然也可以做到很容易的分合,把兩個數據庫合并成一個,或者把一個數據庫分開成兩個,只涉及到配置文件的更改,在開發的時候可以不關心的。

LINQ To SQL和ORM的理解6、對于可變查詢的處理。

也就是相當于拼接字符串了。可能會說,這個是LINQ的強項,但是,如果對于一個分布式的項目呢?又應該如何處理。知道ORM的朋友應該都知道IBatis.net 和NHibnate ,I家的參數處理是非常的方便的,N家呢就沒有I的直觀,但是對于面向對象的處理I比N家好像就有太多的不足了。對于遠程處理要能夠通過參數傳遞這些只對映射層公開的參數,這點對于程序的某些地方可能是至關重要的影響。我的ORM里面,隨便起了一個名字,叫通用查詢,業務邏輯里用的查詢通常會寫在存儲過程里,可以通過工具直接生成業務層代碼里的函數。

LINQ To SQL和ORM的理解7、對于泛形、繼承的支持與處理。

泛形,可以減少很多代碼,同時,還可以減少很多人為的錯誤。

因為人的精力總是有限的,你把精力花在一個地方,那么其他方面肯定關注的少了,我也一樣。可能是我把精力過多的放在我的ORM里面,忽略了其他的方面,請大家能夠給出批評指正。接下來,把我的ORM映射部分做一詳細的介紹

LINQ To SQL和ORM的理解之ORM映射主要分為以下幾個方面:

LINQ To SQL和ORM的理解1、對象、參數翻譯

a)LINQ To SQL和ORM的理解之對象的表達。對象的映射,我采用的是自定義屬性方法。

namespace LG.Common.Enities  {  using System;  using System.Collections.Generic;  using System.Text;  using System.Data;  using System.Data.SqlClient;  using Unie2e.Common;  using Unie2e.ORM;  using Unie2e.ORM.Mapping;  [System.SerializableAttribute()]  [Unie2e.ORM.Mapping.TableAttribute(  "City", MapFileName="CityCustParam.Xml")]  public sealed class CityEntity :   Unie2e.ORM.Mapping.Entity  {  /**//// <summary>  /// 映射字段的總長度  /// </summary>  private const int length = 5;

LINQ To SQL和ORM的理解之映射字段

#region 映射字段   /**//// <summary>   /// 城市Id   /// </summary>   [Unie2e.ORM.Mapping.FieldAttribute(  "City", "CityId", true, SqlDbType.  UniqueIdentifier, 0, 0, 0, "城市Id")]   public Guid CityId = System.Guid.NewGuid();   /**//// <summary>   /// 省份Id   /// </summary>   [Unie2e.ORM.Mapping.FieldAttribute("City",   "ProvinceId", false, SqlDbType.UniqueIdentifier,   0, 0, 0, "省份Id")]   public Guid ProvinceId = System.Guid.Empty;   /**//// <summary>   /// 城市代碼   /// </summary>   [Unie2e.ORM.Mapping.FieldAttribute("City",  "CityCode", false, SqlDbType.VarChar,   50, 0, 0, "城市代碼")]   public String CityCode;   /**//// <summary>   /// 城市名稱   /// </summary>   [Unie2e.ORM.Mapping.FieldAttribute("City",   "CityName", false, SqlDbType.VarChar,   50, 0, 0, "城市名稱")]   public String CityName;   /**//// <summary>   /// 備注   /// </summary>   [Unie2e.ORM.Mapping.FieldAttribute("City",   "CityComment", false, SqlDbType.VarChar,   200, 0, 0, "備注")]   public String CityComment;   #endregion

LINQ To SQL和ORM的理解之重載基類函數

public override void Initialize(object[] parameters)   {   if ((length != parameters.Length))  {  throw new E2EException("參數個數與字段數不相等");  }  CityId = ((System.Guid)(parameters[0]));  ProvinceId = ((System.Guid)(parameters[1]));  CityCode = ((string)(parameters[2]));  CityName = ((string)(parameters[3]));  CityComment = ((string)(parameters[4]));  }  public override object[] ToArray()  {  object[] objs = new object[5];  objs[0] = CityId;  objs[1] = ProvinceId;  objs[2] = CityCode;  objs[3] = CityName;  objs[4] = CityComment;  return objs;  }  #endregion  }  [System.SerializableAttribute()]  [Unie2e.ORM.Mapping.TableAttribute("City")]  public abstract class CityFindParam<T> : EntityParam<T> where T: IEntity  {  /**//// <summary>   /// 映射字段的總長度  /// </summary>  private const int length = 6;

LINQ To SQL和ORM的理解之映射字段

[Unie2e.ORM.Mapping.FieldAttribute(  "City", "Method", SqlDbType.VarChar, 50, 0, 0, "")]   public String Method;   [Unie2e.ORM.Mapping.FieldAttribute("City",   "CityId", SqlDbType.UniqueIdentifier, 0, 0, 0, "")]   public Guid CityId = System.Guid.Empty;   [Unie2e.ORM.Mapping.FieldAttribute("City",   "ProvinceId", SqlDbType.UniqueIdentifier, 0, 0, 0, "")]   public Guid ProvinceId = System.Guid.Empty;   [Unie2e.ORM.Mapping.FieldAttribute("City",   "CityCode", SqlDbType.VarChar, 50, 0, 0, "")]   public String CityCode;   [Unie2e.ORM.Mapping.FieldAttribute("City",   "CityName", SqlDbType.VarChar, 50, 0, 0, "")]   public String CityName;   [Unie2e.ORM.Mapping.FieldAttribute("City",   "CityComment", SqlDbType.VarChar, 200, 0, 0, "")]   public String CityComment;   #endregion

LINQ To SQL和ORM的理解之重載基類函數

public override object[] ToArray()  {  object[] objs = new object[6];  objs[0] = Method;  objs[1] = CityId;  objs[2] = ProvinceId;  objs[3] = CityCode;  objs[4] = CityName;  objs[5] = CityComment;  return objs;  }  public override void Initialize(object[] parameters)  {  if ((length != parameters.Length))  {  throw new E2EException("參數個數與字段數不相等");  }  Method = ((String)(parameters[0]));  CityId = ((Guid)(parameters[1]));  ProvinceId = ((Guid)(parameters[2]));  CityCode = ((String)(parameters[3]));  CityName = ((String)(parameters[4]));  CityComment = ((String)(parameters[5]));  }  #endregion  }  [System.SerializableAttribute()]  [Unie2e.ORM.Mapping.TableAttribute("City")]  public sealed class CityFindParam : CityFindParam<CityEntity>  {  }  [System.SerializableAttribute()]  [Unie2e.ORM.Mapping.TableAttribute("City")]  public abstract class CityActionParam<T> :   EntityParam<T> where T: IEntity   {   /**//// <summary>  /// 映射字段的總長度  /// </summary>  private const int length = 2;  映射字段#region 映射字段  [Unie2e.ORM.Mapping.FieldAttribute("City",   "Method", SqlDbType.VarChar, 50, 0, 0, "")]  public String Method;  [Unie2e.ORM.Mapping.FieldAttribute("City",   "CityId", SqlDbType.UniqueIdentifier, 0, 0, 0, "")]  public Guid CityId = System.Guid.Empty;  #endregion

LINQ To SQL和ORM的理解之重載基類函數

public override object[] ToArray()  {  object[] objs = new object[2];  objs[0] = Method;  objs[1] = CityId;  return objs;  }  public override void Initialize(object[] parameters)  {  if ((length != parameters.Length))  {  throw new E2EException("參數個數與字段數不相等");  }  Method = ((String)(parameters[0]));  CityId = ((Guid)(parameters[1]));  }  #endregion  }   [System.SerializableAttribute()]  [Unie2e.ORM.Mapping.TableAttribute("City")]  public sealed class CityActionParam :   CityActionParam<CityEntity>  {  }  }   [Unie2e.ORM.Mapping.TableAttribute("City",   MapFileName="CityCustParam.Xml")]

給出了映射對象與數據庫表或者視圖的關系,MapFileName給出了所對應的通用查詢的配置文件,當然也可以把Sql語句寫在配置文件里面,實現查詢之外的其他動作處理。因為工具沒有對其他生成代碼函數的支持,所以通常還是通過工具來生成存儲過程來處理。

在Entity里面,有兩上重載的函數:public override void Initialize(object[] parameters)和public override object[] ToArray(),這兩個函數是為了加速數據加載的。底層用的是DataReader讀取數據,盡可能少的通過反射加載數據,實現數據的快速從數據庫加載到對象里面,因為這些代碼都是通過工具生成的,不會出現錯誤,比較要注意的是用工具寫存儲過程的時候要注意一點就可以了。

[Unie2e.ORM.Mapping.FieldAttribute("City", "CityId",    true, SqlDbType.UniqueIdentifier, 0, 0, 0, "城市Id")]

給出了對象Field與表或視圖的列的映射關系。***一個是對于注釋,對于BO的業務數據會生成Summary。最終會生成到界面的表述,以及列表的配置文件的頭。

除了Entity 外,還有CityFindParam<T> ,CityFindParam,CityActionParam<T>,CityActionParam這幾個類,CityFindParam<T> 主要是為了實現可變返回數據,默認情況下返回的是完整表的數據,有時候,數據庫表或視圖的字段很多,比較重要的地方,可能只會要求返回其中的部分字段,用在這方面處理。CityActionParam,主要是針對批量更新等特殊處理,對個別地方進行性能優化處理。

b)LINQ To SQL和ORM的理解之對象翻譯

對象翻譯就是把對象屬性翻譯到成相對應的存儲過程的調用。我的ORM映射主要是對象參數處理。添加、刪除、修改都是對完整的對象的映射,對于特別的處理是通過Action處理的。

SqlParameter[] BuilderSqlParameters(Type type,SQLActionType actionType)  {  FieldInfo[] infos = type.GetFields();  SqlParameter[] parameters =   new SqlParameter[infos.Length];  for (int i = 0; i < infos.Length; i++)  {  object[] objs = infos[i].GetCustomAttributes(typeof(FieldAttribute), false);  FieldAttribute attr = objs[0] as FieldAttribute;  SqlParameter sp;  if (attr.Length != 0)  sp = new SqlParameter("@" + attr.ColumnName, attr.SqlDbType, attr.Length);  else  {   sp = new SqlParameter("@" + attr.ColumnName, attr.SqlDbType);   }   if (attr.IsKey&&actionType== SQLActionType .Insert)   sp.Direction = ParameterDirection.InputOutput;   parameters[i]=sp;  }  }  return parameters;  }

***次執行的時候,遍歷所有字段,根據FieldAttribute 生成調用存儲過程的Command,并緩存,第二次執行的時候,直接從緩存里取出Command 的Clone()。此處調用Clone ,返回的是Command的DeepCopy!!!也是微軟在2.0里面新添加的函數,我估計新加的函數的用處也就是在這里了,極大的提高了處理速度。接下來就是存儲過程的賦值了。

void AssignParameterValues(object instance, SqlCommand cmd)  {  SqlParameterCollection sps = cmd.Parameters;  IEntity idb =instance as IEntity;  if (idb == null)  throw new Exception("存儲過程賦值出錯,要具有IEntity接口");  object[] values = idb.ToArray();  if (values.Length != sps.Count )  throw new Exception("參數個數不一致");  for (int i = 0; i < values.Length; i++)  {  object val = values[i];  //對于時間的空值等,這里還會報錯。一般要求要有初始化。  sps[i].Value =null == val ?System.DBNull.Value:val;  }  }

剛剛介紹了在Entity和ParamEntity里面有兩個重載的虛函數函數,其中一個是:ToArray(),在這里用到了。如果是通過反射得到實例的值,那效率實在是太低了,這里用了IEntity的ToArray(),因為映射的順序位置都是固定的,所以可以通過數組的方式實現。這也是工具的重要的地方,靠手工處理,錯誤的幾率太高了。

現在存儲過程是可以正常調用了,正常的 增、改、刪,是可以處理了,下面介紹取數據。

c)LINQ To SQL和ORM的理解之數據讀取加載

數據加載主要是通過DataReader實現的。

object GetFindResult(IDataReader reader, Type targetType)  {  Type target = targetType;  object[] fields = new object[reader.FieldCount];  IEntity t = (IEntity)Activator.CreateInstance(target);  Type constructed = typeof(ORMCollection<>).  MakeGenericType(target);  IList list = (IList)Activator.CreateInstance(constructed);  while (reader.Read())  {  for (int i = 0; i < fields.Length; i++)  {   fields[i] = reader.IsDBNull(i) ? null : reader[i];  }  t.Initialize(fields);  list.Add(t.Clone());  }  return list;  }  object GetFindResult(IDataReader reader,   Type targetType, int currentpage, int pagesize)

數據加載提供了2個函數,一個是帶分頁一個是不帶分頁。IEntity提供的幾個接口在這里都用了,也主要是為了這里準備的。也主要是在此實現了數據的快速加載。主要體現在兩個上面,一個是t.Initialize(fields),Initialize 在上面是介紹了,不用通過反射初始化及賦值,再者是 t.Clone(),用的也是DeepCopy,不是用Activator 創建新的對象實例,因為Activator 構造對象的時候速度跟DeepCopy相比,要慢了很多。

還有一個是我自封的通用查詢,也就是通過MapFileName 找到配置文件,把Sql配置文件加載進來,翻譯成Command加到緩存里面,后期的處理與上面的一樣,在這里就不再過多的介紹了,只把關鍵代碼列出來。

string BuildFind(FieldInfo[] pis, FinderParam finderParam,   out SqlParameter[] parameters)  {  ORMCollection<FinderParamItem> items =   finderParam.ParamItemCollection;  if (items==null)   throw new E2EException("ParamItemCollection參數不能為空");  StringBuilder sb = new StringBuilder();  List<SqlParameter> parameterList = new List<SqlParameter>();  foreach (FinderParamItem var in items)  {  FieldInfo pi = Array.Find(pis, delegate(FieldInfo obj) {   return obj.Name.Equals(var.PropertyName,   StringComparison.OrdinalIgnoreCase); });   if (pi == null)    throw new E2EException("不存在參數:"+var.PropertyName);    object[] attribs = pi.GetCustomAttributes(  typeof(FieldAttribute), false);   if (attribs.Length == 0)  continue;  FieldAttribute attr = attribs[0] as FieldAttribute;  string typeName = pi.FieldType.Name;  if (sb.Length != 0)  {  switch (var.JoinKey)  {  case JoinKey.與:   sb.Append(" AND ");   break;   case JoinKey.或:   sb.Append(" OR ");   break;   default:   break;   }  }  sb.Append(" (");   sb.Append(attr.TableName+"."+attr.ColumnName);   switch (var.ComparisonKey)   {   case ComparisonKey.等于:   sb.Append("=");   break;   case ComparisonKey.不等于:   sb.Append("<>");   break;   case ComparisonKey.大于:   sb.Append(">");   break;   case ComparisonKey.小于:   sb.Append("<");   break;   case ComparisonKey.大于等于:   sb.Append(">=");   break;   case ComparisonKey.小于等于:   sb.Append("<=");   break;   case ComparisonKey.包含:   sb.Append(" like ");   break;   case ComparisonKey.不含:   sb.Append("<>");   break;   default:   break;  }   sb.Append("@" + pi.Name + ")");  SqlParameter param = new SqlParameter();  param.ParameterName = "@" + pi.Name;  param.SqlDbType = attr.SqlDbType;  param.Size = attr.Length;  param.Scale = (byte)attr.XScale;  param.Precision = (byte)attr.XPrec;  param.IsNullable = true;  parameterList.Add(param);  sb.Append(" ");  }  if (sb.Length > 0)  sb.Insert(0, " WHERE ");  parameters = parameterList.ToArray();  return sb.ToString();  }

到此,基本ORM 映射的處理已經介紹完了,映射的代碼都是通過工具生成的,不用人工去處理,曾考慮直接生成Dll的,包括存儲過程,都是工具與之配套的,至少不用寫千篇一率的Insert、Update、Delete、FindById這些枯燥的存儲過程了,如果是通過外鍵關聯的,相關的存儲過程也是自動生成的,盡可能減少人工處理過程。(建立的時候可以把外鍵全部進來,代碼生成完之后,再把外鍵去掉,偷工減料的做法,偶經常做 ^_^)

當然,這里只是ORM 處理,還沒有把業務邏輯層關聯起來,大家最關注的還是業務邏輯處理,這才是核心,我只所以不想更換ORM,部分是由于我的邏輯層的組織。

感謝各位的閱讀,以上就是“LINQ To SQL和ORM怎么理解”的內容了,經過本文的學習后,相信大家對LINQ To SQL和ORM怎么理解這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

陆良县| 宝清县| 中牟县| 涿鹿县| 佛山市| 高密市| 潮州市| 芜湖县| 娄烦县| 惠州市| 开鲁县| 洛隆县| 鄂尔多斯市| 凤山市| 增城市| 历史| 广饶县| 临漳县| 封丘县| 屏东县| 泰兴市| 建始县| 五指山市| 抚顺市| 新安县| 临桂县| 嘉禾县| 兴山县| 堆龙德庆县| 静乐县| 苗栗市| 精河县| 宝鸡市| 蕲春县| 定襄县| 湛江市| 龙海市| 尖扎县| 新建县| 德钦县| 营口市|