這篇文章主要講解了“LINQ To SQL和ORM怎么理解”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“LINQ To SQL和ORM怎么理解”吧!
成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),西安企業(yè)網(wǎng)站建設(shè),西安品牌網(wǎng)站建設(shè),網(wǎng)站定制,西安網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,西安網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
LINQ To SQL和ORM的理解1、
沒有LINQ的源代碼,不知道清楚中間的數(shù)據(jù)是如何處理的,特別是緩存是如何處理的。
LINQ To SQL和ORM的理解2、
用LINQ翻譯到存儲(chǔ)過程/Sql語句效率很低的,對(duì)于復(fù)雜的對(duì)效率有一定的要求的,還是要寫存儲(chǔ)過程。而且翻譯出來的存儲(chǔ)過程/Sql語句的怎么緩存,第二次執(zhí)行的時(shí)候還要重新翻譯,不能很好的利用緩存。
LINQ To SQL和ORM的理解3、工具的支持。
這一點(diǎn)是非常重要。如果沒有有力工具的支持,用ORM簡(jiǎn)直就是惡夢(mèng)。LINQ的工具支持總的來說,現(xiàn)在在VS2008里的支持我感覺還不是很友好。至少有一點(diǎn),我們通常在表的備注里面寫下這個(gè)字段的注釋,很多情況下對(duì)應(yīng)到界面上就是這個(gè)字段的抬頭,這個(gè)工具不能直接生成到項(xiàng)目里去,因?yàn)槲覀儾荒芸刂?,再者,現(xiàn)在的項(xiàng)目都不是由一個(gè)人完成,如果一個(gè)類有幾十個(gè)字段,很難記住解釋,自己的工具可以加入注釋,方便開發(fā)。
LINQ To SQL和ORM的理解4、與業(yè)務(wù)層的綜合。
通常ORM映射就是把對(duì)象與關(guān)系表之間形成映射關(guān)系,映射的目標(biāo)是為了方便業(yè)務(wù)層的邏輯處理,如果不能與業(yè)務(wù)層無縫的結(jié)合起來,那么對(duì)于項(xiàng)目的開發(fā),也未必有多少好處。至少在的ORM里面,與的我業(yè)務(wù)層可以非常友好的集成在一起。
LINQ To SQL和ORM的理解5、多數(shù)據(jù)源的支持。
對(duì)于我來說,這點(diǎn)也是非常關(guān)鍵的。我說的多數(shù)據(jù)源是指一個(gè)項(xiàng)目里面,有多個(gè)數(shù)據(jù)庫(kù),比如:基礎(chǔ)數(shù)據(jù)、客戶管理、業(yè)務(wù)運(yùn)作、權(quán)限管理等,這些都是相對(duì)獨(dú)立的模塊,開發(fā)的時(shí)候,可以把這幾個(gè)作為單獨(dú)的項(xiàng)目開發(fā),各自有自己獨(dú)立的數(shù)據(jù)庫(kù),而且在多個(gè)項(xiàng)目里面,這些模塊都是非常相似,像權(quán)限模塊基本上是通用的,沒有必要再重復(fù)開發(fā)。如果能夠做到數(shù)據(jù)庫(kù)層分離,則新項(xiàng)目開發(fā)的時(shí)候,可以達(dá)到更快的速度。當(dāng)然也可以做到很容易的分合,把兩個(gè)數(shù)據(jù)庫(kù)合并成一個(gè),或者把一個(gè)數(shù)據(jù)庫(kù)分開成兩個(gè),只涉及到配置文件的更改,在開發(fā)的時(shí)候可以不關(guān)心的。
LINQ To SQL和ORM的理解6、對(duì)于可變查詢的處理。
也就是相當(dāng)于拼接字符串了。可能會(huì)說,這個(gè)是LINQ的強(qiáng)項(xiàng),但是,如果對(duì)于一個(gè)分布式的項(xiàng)目呢?又應(yīng)該如何處理。知道ORM的朋友應(yīng)該都知道IBatis.net 和NHibnate ,I家的參數(shù)處理是非常的方便的,N家呢就沒有I的直觀,但是對(duì)于面向?qū)ο蟮奶幚鞩比N家好像就有太多的不足了。對(duì)于遠(yuǎn)程處理要能夠通過參數(shù)傳遞這些只對(duì)映射層公開的參數(shù),這點(diǎn)對(duì)于程序的某些地方可能是至關(guān)重要的影響。我的ORM里面,隨便起了一個(gè)名字,叫通用查詢,業(yè)務(wù)邏輯里用的查詢通常會(huì)寫在存儲(chǔ)過程里,可以通過工具直接生成業(yè)務(wù)層代碼里的函數(shù)。
LINQ To SQL和ORM的理解7、對(duì)于泛形、繼承的支持與處理。
泛形,可以減少很多代碼,同時(shí),還可以減少很多人為的錯(cuò)誤。
因?yàn)槿说木偸怯邢薜?,你把精力花在一個(gè)地方,那么其他方面肯定關(guān)注的少了,我也一樣??赡苁俏野丫^多的放在我的ORM里面,忽略了其他的方面,請(qǐng)大家能夠給出批評(píng)指正。接下來,把我的ORM映射部分做一詳細(xì)的介紹
LINQ To SQL和ORM的理解之ORM映射主要分為以下幾個(gè)方面:
LINQ To SQL和ORM的理解1、對(duì)象、參數(shù)翻譯
a)LINQ To SQL和ORM的理解之對(duì)象的表達(dá)。對(duì)象的映射,我采用的是自定義屬性方法。
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> /// 映射字段的總長(zhǎng)度 /// </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的理解之重載基類函數(shù)
public override void Initialize(object[] parameters) { if ((length != parameters.Length)) { throw new E2EException("參數(shù)個(gè)數(shù)與字段數(shù)不相等"); } 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> /// 映射字段的總長(zhǎng)度 /// </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的理解之重載基類函數(shù)
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("參數(shù)個(gè)數(shù)與字段數(shù)不相等"); } 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> /// 映射字段的總長(zhǎng)度 /// </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的理解之重載基類函數(shù)
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("參數(shù)個(gè)數(shù)與字段數(shù)不相等"); } 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")]
給出了映射對(duì)象與數(shù)據(jù)庫(kù)表或者視圖的關(guān)系,MapFileName給出了所對(duì)應(yīng)的通用查詢的配置文件,當(dāng)然也可以把Sql語句寫在配置文件里面,實(shí)現(xiàn)查詢之外的其他動(dòng)作處理。因?yàn)楣ぞ邲]有對(duì)其他生成代碼函數(shù)的支持,所以通常還是通過工具來生成存儲(chǔ)過程來處理。
在Entity里面,有兩上重載的函數(shù):public override void Initialize(object[] parameters)和public override object[] ToArray(),這兩個(gè)函數(shù)是為了加速數(shù)據(jù)加載的。底層用的是DataReader讀取數(shù)據(jù),盡可能少的通過反射加載數(shù)據(jù),實(shí)現(xiàn)數(shù)據(jù)的快速?gòu)臄?shù)據(jù)庫(kù)加載到對(duì)象里面,因?yàn)檫@些代碼都是通過工具生成的,不會(huì)出現(xiàn)錯(cuò)誤,比較要注意的是用工具寫存儲(chǔ)過程的時(shí)候要注意一點(diǎn)就可以了。
[Unie2e.ORM.Mapping.FieldAttribute("City", "CityId", true, SqlDbType.UniqueIdentifier, 0, 0, 0, "城市Id")]
給出了對(duì)象Field與表或視圖的列的映射關(guān)系。***一個(gè)是對(duì)于注釋,對(duì)于BO的業(yè)務(wù)數(shù)據(jù)會(huì)生成Summary。最終會(huì)生成到界面的表述,以及列表的配置文件的頭。
除了Entity 外,還有CityFindParam<T> ,CityFindParam,CityActionParam<T>,CityActionParam這幾個(gè)類,CityFindParam<T> 主要是為了實(shí)現(xiàn)可變返回?cái)?shù)據(jù),默認(rèn)情況下返回的是完整表的數(shù)據(jù),有時(shí)候,數(shù)據(jù)庫(kù)表或視圖的字段很多,比較重要的地方,可能只會(huì)要求返回其中的部分字段,用在這方面處理。CityActionParam,主要是針對(duì)批量更新等特殊處理,對(duì)個(gè)別地方進(jìn)行性能優(yōu)化處理。
b)LINQ To SQL和ORM的理解之對(duì)象翻譯
對(duì)象翻譯就是把對(duì)象屬性翻譯到成相對(duì)應(yīng)的存儲(chǔ)過程的調(diào)用。我的ORM映射主要是對(duì)象參數(shù)處理。添加、刪除、修改都是對(duì)完整的對(duì)象的映射,對(duì)于特別的處理是通過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; }
***次執(zhí)行的時(shí)候,遍歷所有字段,根據(jù)FieldAttribute 生成調(diào)用存儲(chǔ)過程的Command,并緩存,第二次執(zhí)行的時(shí)候,直接從緩存里取出Command 的Clone()。此處調(diào)用Clone ,返回的是Command的DeepCopy?。?!也是微軟在2.0里面新添加的函數(shù),我估計(jì)新加的函數(shù)的用處也就是在這里了,極大的提高了處理速度。接下來就是存儲(chǔ)過程的賦值了。
void AssignParameterValues(object instance, SqlCommand cmd) { SqlParameterCollection sps = cmd.Parameters; IEntity idb =instance as IEntity; if (idb == null) throw new Exception("存儲(chǔ)過程賦值出錯(cuò),要具有IEntity接口"); object[] values = idb.ToArray(); if (values.Length != sps.Count ) throw new Exception("參數(shù)個(gè)數(shù)不一致"); for (int i = 0; i < values.Length; i++) { object val = values[i]; //對(duì)于時(shí)間的空值等,這里還會(huì)報(bào)錯(cuò)。一般要求要有初始化。 sps[i].Value =null == val ?System.DBNull.Value:val; } }
剛剛介紹了在Entity和ParamEntity里面有兩個(gè)重載的虛函數(shù)函數(shù),其中一個(gè)是:ToArray(),在這里用到了。如果是通過反射得到實(shí)例的值,那效率實(shí)在是太低了,這里用了IEntity的ToArray(),因?yàn)橛成涞捻樞蛭恢枚际枪潭ǖ?,所以可以通過數(shù)組的方式實(shí)現(xiàn)。這也是工具的重要的地方,靠手工處理,錯(cuò)誤的幾率太高了。
現(xiàn)在存儲(chǔ)過程是可以正常調(diào)用了,正常的 增、改、刪,是可以處理了,下面介紹取數(shù)據(jù)。
c)LINQ To SQL和ORM的理解之?dāng)?shù)據(jù)讀取加載
數(shù)據(jù)加載主要是通過DataReader實(shí)現(xiàn)的。
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)
數(shù)據(jù)加載提供了2個(gè)函數(shù),一個(gè)是帶分頁一個(gè)是不帶分頁。IEntity提供的幾個(gè)接口在這里都用了,也主要是為了這里準(zhǔn)備的。也主要是在此實(shí)現(xiàn)了數(shù)據(jù)的快速加載。主要體現(xiàn)在兩個(gè)上面,一個(gè)是t.Initialize(fields),Initialize 在上面是介紹了,不用通過反射初始化及賦值,再者是 t.Clone(),用的也是DeepCopy,不是用Activator 創(chuàng)建新的對(duì)象實(shí)例,因?yàn)锳ctivator 構(gòu)造對(duì)象的時(shí)候速度跟DeepCopy相比,要慢了很多。
還有一個(gè)是我自封的通用查詢,也就是通過MapFileName 找到配置文件,把Sql配置文件加載進(jìn)來,翻譯成Command加到緩存里面,后期的處理與上面的一樣,在這里就不再過多的介紹了,只把關(guān)鍵代碼列出來。
string BuildFind(FieldInfo[] pis, FinderParam finderParam, out SqlParameter[] parameters) { ORMCollection<FinderParamItem> items = finderParam.ParamItemCollection; if (items==null) throw new E2EException("ParamItemCollection參數(shù)不能為空"); 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("不存在參數(shù):"+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 映射的處理已經(jīng)介紹完了,映射的代碼都是通過工具生成的,不用人工去處理,曾考慮直接生成Dll的,包括存儲(chǔ)過程,都是工具與之配套的,至少不用寫千篇一率的Insert、Update、Delete、FindById這些枯燥的存儲(chǔ)過程了,如果是通過外鍵關(guān)聯(lián)的,相關(guān)的存儲(chǔ)過程也是自動(dòng)生成的,盡可能減少人工處理過程。(建立的時(shí)候可以把外鍵全部進(jìn)來,代碼生成完之后,再把外鍵去掉,偷工減料的做法,偶經(jīng)常做 ^_^)
當(dāng)然,這里只是ORM 處理,還沒有把業(yè)務(wù)邏輯層關(guān)聯(lián)起來,大家最關(guān)注的還是業(yè)務(wù)邏輯處理,這才是核心,我只所以不想更換ORM,部分是由于我的邏輯層的組織。
感謝各位的閱讀,以上就是“LINQ To SQL和ORM怎么理解”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)LINQ To SQL和ORM怎么理解這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
當(dāng)前名稱:LINQToSQL和ORM怎么理解
轉(zhuǎn)載來源:http://jinyejixie.com/article36/jopopg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營(yíng)銷型網(wǎng)站建設(shè)、云服務(wù)器、電子商務(wù)、軟件開發(fā)、定制開發(fā)、虛擬主機(jī)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)