日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

[原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(前篇)...

發(fā)布時(shí)間:2025/7/14 asp.net 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(前篇)... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

.NET 業(yè)務(wù)框架開(kāi)發(fā)實(shí)戰(zhàn)之十 第一階段總結(jié),深入淺出,水到渠成(前篇)

  前言:這個(gè)系列有段時(shí)間沒(méi)有動(dòng)了。主要是針對(duì)大家的反饋在修改代碼。在修改的過(guò)程中,也有了一些新的體會(huì),這里和大家分享一下,同時(shí)也發(fā)布一下業(yè)務(wù)框架的第一個(gè)版本。在本篇文章中,學(xué)習(xí)到的不是僅僅只是代碼,而是設(shè)計(jì)的思想和實(shí)現(xiàn)這種思想的方法。在寫(xiě)本篇時(shí)有個(gè)感觸:把一個(gè)東西徹底的講清楚,不容易。希望大家

多提意見(jiàn)。而且在寫(xiě)本篇的時(shí)候,我個(gè)人也是很興奮的,至于原因相信大家在看完之后就知道了。J

本篇的議題如下:

1.????? 打通業(yè)務(wù)層和數(shù)據(jù)層

2.????? 打通方法的選擇和實(shí)現(xiàn)

3.????? 再次借鑒.NET Framework設(shè)計(jì)思想

4.????? 水到渠成

5.????? 代碼的版本說(shuō)明

?

  系列文章鏈接:

?[原創(chuàng)].NET 分布式架構(gòu)開(kāi)發(fā)實(shí)戰(zhàn)之一 故事起源

[原創(chuàng)].NET 分布式架構(gòu)開(kāi)發(fā)實(shí)戰(zhàn)之二 草稿設(shè)計(jì)

[原創(chuàng)].NET 分布式架構(gòu)開(kāi)發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問(wèn)深入一點(diǎn)的思考

[原創(chuàng)].NET 分布式架構(gòu)開(kāi)發(fā)實(shí)戰(zhàn)之四 構(gòu)建從理想和實(shí)現(xiàn)之間的橋梁(前篇)

[原創(chuàng)].NET 分布式架構(gòu)開(kāi)發(fā)實(shí)戰(zhàn)五 Framework改進(jìn)篇

[原創(chuàng)].NET 業(yè)務(wù)框架開(kāi)發(fā)實(shí)戰(zhàn)之六 DAL的重構(gòu)

[原創(chuàng)].NET 業(yè)務(wù)框架開(kāi)發(fā)實(shí)戰(zhàn)之七 業(yè)務(wù)層初步構(gòu)想

[原創(chuàng)].NET 業(yè)務(wù)框架開(kāi)發(fā)實(shí)戰(zhàn)之八 業(yè)務(wù)層Mapping的選擇策略

[原創(chuàng)].NET 業(yè)務(wù)框架開(kāi)發(fā)實(shí)戰(zhàn)之九 Mapping屬性原理和驗(yàn)證規(guī)則的實(shí)現(xiàn)策略

[原創(chuàng)].NET 業(yè)務(wù)框架開(kāi)發(fā)實(shí)戰(zhàn)之十 第一階段總結(jié),深入淺出,水到渠成(前篇)

[原創(chuàng)].NET 業(yè)務(wù)框架開(kāi)發(fā)實(shí)戰(zhàn)之十 第一階段總結(jié),深入淺出,水到渠成(后篇)

?

1.??? 打通業(yè)務(wù)層和數(shù)據(jù)層

首先,回顧之前的文章一直討論的問(wèn)題:

1. 如何使得數(shù)據(jù)層”以不變應(yīng)萬(wàn)變”。

2. 條件對(duì)象如何實(shí)現(xiàn)

3. 如何在業(yè)務(wù)層和數(shù)據(jù)層之間mapping數(shù)據(jù)

本篇就告訴大家,如何切切實(shí)實(shí)的解決上面三個(gè)問(wèn)題。

?

首先,從一個(gè)圖示開(kāi)始講述。

?

?

從上面的圖中可以看出,架起在BLL和DAL之前的橋梁的就是中間的那個(gè)條件對(duì)象。正是因?yàn)橛辛诉@個(gè),所以上面的提出的問(wèn)題才得以解決。

下面先從操作上總體來(lái)講述一下這個(gè)圖的具體流程:

a.?????? 在業(yè)務(wù)類(lèi)中創(chuàng)建一個(gè)方法。例如在業(yè)務(wù)類(lèi)User中,定義如下:

現(xiàn)在只看GetUserByAge這個(gè)方法:在方法中構(gòu)造出一個(gè)條件對(duì)象,大家第一眼能看出來(lái):是Linq的實(shí)現(xiàn)。其實(shí)最后的實(shí)現(xiàn)只是借用了Linq的思想,僅此而已

b.?????? 解析條件對(duì)象。在上面的構(gòu)造的條件對(duì)象中,Age,Name等,都是業(yè)務(wù)類(lèi)User的字段,這些字段的值肯定最終是從數(shù)據(jù)庫(kù)中的表字段中獲取的(或者是通過(guò)數(shù)據(jù)庫(kù)中的值算出來(lái)的),所以在解析條件對(duì)象的時(shí)候,就要知道這些業(yè)務(wù)屬性對(duì)應(yīng)數(shù)據(jù)庫(kù)中哪個(gè)表的哪個(gè)字段。因此在業(yè)務(wù)類(lèi)中聲明每個(gè)屬性的時(shí)候就要同時(shí)保留它所對(duì)應(yīng)的數(shù)據(jù)庫(kù)字段的信息。一旦業(yè)務(wù)類(lèi)的屬性中保存了這些信息

c.?????? 數(shù)據(jù)層操作SQL語(yǔ)句。在解析條件對(duì)象的時(shí)候,就會(huì)最終得到相對(duì)應(yīng)的SQL語(yǔ)句,然后在數(shù)據(jù)層中執(zhí)行這些SQL語(yǔ)句。

可能上面講的比較的抽象,因?yàn)楸酒囊v述的東西確實(shí)比較的多(Word中寫(xiě)了超過(guò)了10頁(yè)),上面講述的三個(gè)步驟也是先按大家有個(gè)印象。不是很懂也沒(méi)有關(guān)系。

?

?2.?打通方法的選擇和實(shí)現(xiàn)

?????? 接下來(lái)就是方法的探索和思考,以及實(shí)現(xiàn)的過(guò)程。我是想帶著個(gè)大家跟著一起看看,為什么最后會(huì)采用這個(gè)解決方案的。

首先,就從條件對(duì)象開(kāi)始看起。

在實(shí)現(xiàn)條件對(duì)象(條件對(duì)象和查詢(xún)對(duì)象的區(qū)別之前講過(guò),這里重述一下:查詢(xún)對(duì)象只是條件對(duì)象的一個(gè)子集,查詢(xún)對(duì)象用來(lái)在查詢(xún)的使用構(gòu)造查詢(xún)條件;條件對(duì)象不僅僅在查詢(xún)時(shí)構(gòu)造條件,而且在增加,刪除,,修改時(shí)候也使用,例如:只修改Name=”admin”的數(shù)據(jù),在修改數(shù)據(jù)庫(kù)的時(shí)候也用了一定的條件。所以條件對(duì)象>查詢(xún)對(duì)象)的時(shí)候,也是參看了其他開(kāi)源框架的一些實(shí)現(xiàn)(Nhibernate中查詢(xún)對(duì)象的,CSLA)。

同時(shí)要明白一點(diǎn):設(shè)計(jì)出來(lái)的框架是給開(kāi)發(fā)人員使用的,所以要考慮如何使得開(kāi)發(fā)人員最快最好的使用框架,所以要從開(kāi)發(fā)人員的角度看(這一點(diǎn)也是很重要的)。例如在Nhibernate中查詢(xún)對(duì)象,使用的方法如下(僅僅是簡(jiǎn)單的舉例而已):

代碼 ?IListCustomer>?customers?=?_session.CreateCriteria(typeof(Customer))
????????.Add(Restrictions.Like(
"Firstname",?"Xiaoyang%"))
????????.Add(Restrictions.Between(
"Lastname",?"A%",?"Y%"))
????????.ListCustomer
>(); ? 其實(shí)本系列中的業(yè)務(wù)框架之前的條件對(duì)象的構(gòu)造也是參看了Nhibernate中查詢(xún)對(duì)象的方法來(lái)實(shí)現(xiàn)和使用的,如下:

?

ICriteria?condition=CriteriaFactory.Create(typeof(ProductBL).Where("ProductName",?Operation.Equal,"book");

?因?yàn)楝F(xiàn)在.NET中的開(kāi)發(fā)人員對(duì)Linq的一些操作比較的熟悉,而且如果把條件對(duì)象的使用方式改為下面的方式:

ICriteria<ProductBL>?condition=CriteriaFactory.Create<ProductBL>(o?=>?o.ProductName?==?"book");

?  

  那么開(kāi)發(fā)人員的學(xué)習(xí)成本就幾乎為零(因?yàn)樗麄兪煜inq,如果條件對(duì)象也采用這種比較統(tǒng)一的方法實(shí)現(xiàn),他們就可以采用”以此類(lèi)推”的思想來(lái)使用框架),更多的好處我就不說(shuō)了,大家可以自己體會(huì)或者參看本系列之前的文章。

?

接下來(lái)就探索實(shí)現(xiàn)條件對(duì)象的方法(Linq to XXX篇)

熟悉Linq的朋友可以看出:可以使條件對(duì)象實(shí)現(xiàn)IQueryable接口,然后采用實(shí)現(xiàn)linq to XXX的方法,實(shí)現(xiàn)自己的Linq Provider。這個(gè)方法是否可行,下面,我們就深入linq to XXX的來(lái)看一看,看完之后,結(jié)果就很清楚了。

首先來(lái)看下面兩個(gè)接口:?

代碼 ??public?interface?IQueryable?:?IEnumerable?{????????
????????Type?ElementType?{?
get;?}
????????Expression?Expression?{?
get;?}
????????IQueryProvider?Provider?{?
get;?}
????}

????public?interface?IQueryable<T>?:?IEnumerable<T>,?IQueryable,?IEnumerable?{} ?   ?public interface IQueryProvider {

??????? IQueryable CreateQuery(Expression expression);

??????? IQueryable<TElement> CreateQuery<TElement>(Expression expression);

??????? object Execute(Expression expression);

??????? TResult Execute<TResult>(Expression expression);

??? }


??

Linq的出現(xiàn),使得很多東西都和linq扯上了關(guān)系:Linq to sql, Linq to Google, Linq to javascript, Linq to Nhibernate...... 所列出來(lái)的這些,我們統(tǒng)稱(chēng)為linq to XXX。這些Linq to XXX都是實(shí)現(xiàn)了上面兩個(gè)接口。

下面就通過(guò)自己實(shí)現(xiàn)linq to sql來(lái)舉例分析。

從總體來(lái)看:linq to sql的本質(zhì)就是:把操作轉(zhuǎn)換為sql語(yǔ)句,然后用ADO.NET執(zhí)行,最后把結(jié)果轉(zhuǎn)換為實(shí)體返回。

其實(shí)下面列出了這么多的代碼,其中最關(guān)鍵的其實(shí)就是QueryProvider中的Execute方法:這個(gè)方法負(fù)責(zé)把你的操作進(jìn)行解析,其實(shí)真正負(fù)責(zé)解析的QueryTranslator。

?

代碼 ?public?class?Query<T>?:?IQueryable<T>,?IQueryable,?IEnumerable<T>,?IEnumerable,?IOrderedQueryable<T>,?IOrderedQueryable?{
????????QueryProvider?provider;
????????Expression?expression;
?

????????
public?Query(QueryProvider?provider)?{
????????????
if?(provider?==?null)?{
????????????????
throw?new?ArgumentNullException("provider");
????????????}
????????????
this.provider?=?provider;
????????????
this.expression?=?Expression.Constant(this);
????????}
?

????????
public?Query(QueryProvider?provider,?Expression?expression)?{
????????????
if?(provider?==?null)?{
????????????????
throw?new?ArgumentNullException("provider");
????????????}
????????????
if?(expression?==?null)?{
????????????????
throw?new?ArgumentNullException("expression");
????????????}
????????????
if?(!typeof(IQueryable<T>).IsAssignableFrom(expression.Type))?{
????????????????
throw?new?ArgumentOutOfRangeException("expression");
????????????}
????????????
this.provider?=?provider;?
????????????
this.expression?=?expression;
????????}
?

????????Expression?IQueryable.Expression?{
????????????
get?{?return?this.expression;?}
????????}
?

????????Type?IQueryable.ElementType?{
????????????
get?{?return?typeof(T);?}
????????}
?

????????IQueryProvider?IQueryable.Provider?{
????????????
get?{?return?this.provider;?}
????????}
?

????????
public?IEnumerator<T>?GetEnumerator()?{
????????????
return?((IEnumerable<T>)this.provider.Execute(this.expression)).GetEnumerator();
????????}
?

????????IEnumerator?IEnumerable.GetEnumerator()?{
????????????
return?((IEnumerable)this.provider.Execute(this.expression)).GetEnumerator();
????????}
?

????????
public?override?string?ToString()?{
????????????
return?this.provider.GetQueryText(this.expression);
????????}
????}

?

?

代碼 public?abstract?class?QueryProvider?:?IQueryProvider?{
????????
protected?QueryProvider()?{
????????}
?

????????IQueryable
<S>?IQueryProvider.CreateQuery<S>(Expression?expression)?{
????????????
return?new?Query<S>(this,?expression);
????????}
?

????????IQueryable?IQueryProvider.CreateQuery(Expression?expression)?{
????????????Type?elementType?
=?TypeSystem.GetElementType(expression.Type);
????????????
try?{
????????????????
return?(IQueryable)Activator.CreateInstance(typeof(Query<>).MakeGenericType(elementType),?new?object[]?{?this,?expression?});
????????????}
????????????
catch?(TargetInvocationException?tie)?{
????????????????
throw?tie.InnerException;
????????????}
????????}
?

????????S?IQueryProvider.Execute
<S>(Expression?expression)?{
????????????
return?(S)this.Execute(expression);
????????}
?

????????
object?IQueryProvider.Execute(Expression?expression)?{
????????????
return?this.Execute(expression);
????????}
?

????????
public?abstract?string?GetQueryText(Expression?expression);
????????
public?abstract?object?Execute(Expression?expression);
????}

?

?

?

代碼 internal?class?QueryTranslator?:?ExpressionVisitor?{
????StringBuilder?sb;
?

????
internal?QueryTranslator()?{
????}
?

????
internal?string?Translate(Expression?expression)?{
????????
this.sb?=?new?StringBuilder();
????????
this.Visit(expression);
????????
return?this.sb.ToString();
????}
?

????
private?static?Expression?StripQuotes(Expression?e)?{
????????
while?(e.NodeType?==?ExpressionType.Quote)?{
????????????e?
=?((UnaryExpression)e).Operand;
????????}
????????
return?e;
????}
?

????
protected?override?Expression?VisitMethodCall(MethodCallExpression?m)?{
????????
if?(m.Method.DeclaringType?==?typeof(Queryable)?&&?m.Method.Name?==?"Where")?{
????????????sb.Append(
"SELECT?*?FROM?(");
????????????
this.Visit(m.Arguments[0]);
????????????sb.Append(
")?AS?T?WHERE?");
????????????LambdaExpression?lambda?
=?(LambdaExpression)StripQuotes(m.Arguments[1]);
????????????
this.Visit(lambda.Body);
????????????
return?m;
????????}
????????
throw?new?NotSupportedException(string.Format("The?method?'{0}'?is?not?supported",?m.Method.Name));
????}
?

????
protected?override?Expression?VisitUnary(UnaryExpression?u)?{
????????
switch?(u.NodeType)?{
????????????
case?ExpressionType.Not:
????????????????sb.Append(
"?NOT?");
????????????????
this.Visit(u.Operand);
????????????????
break;
????????????
default:
????????????????
throw?new?NotSupportedException(string.Format("The?unary?operator?'{0}'?is?not?supported",?u.NodeType));
????????}
????????
return?u;
????}
?

????
protected?override?Expression?VisitBinary(BinaryExpression?b)?{
????????sb.Append(
"(");
????????
this.Visit(b.Left);
????????
switch?(b.NodeType)?{
????????????
case?ExpressionType.And:
????????????????sb.Append(
"?AND?");
????????????????
break;
????????????
case?ExpressionType.Or:
????????????????sb.Append(
"?OR");
????????????????
break;
????????????
case?ExpressionType.Equal:
????????????????sb.Append(
"?=?");
????????????????
break;
????????????
case?ExpressionType.NotEqual:
????????????????sb.Append(
"?<>?");
????????????????
break;
????????????
case?ExpressionType.LessThan:
????????????????sb.Append(
"?<?");
????????????????
break;
????????????
case?ExpressionType.LessThanOrEqual:
????????????????sb.Append(
"?<=?");
????????????????
break;
????????????
case?ExpressionType.GreaterThan:
????????????????sb.Append(
"?>?");
????????????????
break;
????????????
case?ExpressionType.GreaterThanOrEqual:
????????????????sb.Append(
"?>=?");
????????????????
break;
????????????
default:
????????????????
throw?new?NotSupportedException(string.Format("The?binary?operator?'{0}'?is?not?supported",?b.NodeType));
????????}
????????
this.Visit(b.Right);
????????sb.Append(
")");
????????
return?b;
????}
?

????
protected?override?Expression?VisitConstant(ConstantExpression?c)?{
????????IQueryable?q?
=?c.Value?as?IQueryable;
????????
if?(q?!=?null)?{
????????????
//?assume?constant?nodes?w/?IQueryables?are?table?references
????????????sb.Append("SELECT?*?FROM?");
????????????sb.Append(q.ElementType.Name);
????????}
????????
else?if?(c.Value?==?null)?{
????????????sb.Append(
"NULL");
????????}
????????
else?{
????????????
switch?(Type.GetTypeCode(c.Value.GetType()))?{
????????????????
case?TypeCode.Boolean:
????????????????????sb.Append(((
bool)c.Value)???1?:?0);
????????????????????
break;
????????????????
case?TypeCode.String:
????????????????????sb.Append(
"'");
????????????????????sb.Append(c.Value);
????????????????????sb.Append(
"'");
????????????????????
break;
????????????????
case?TypeCode.Object:
????????????????????
throw?new?NotSupportedException(string.Format("The?constant?for?'{0}'?is?not?supported",?c.Value));
????????????????
default:
????????????????????sb.Append(c.Value);
????????????????????
break;
????????????}
????????}
????????
return?c;
????}
?

????
protected?override?Expression?VisitMemberAccess(MemberExpression?m)?{
????????
if?(m.Expression?!=?null?&&?m.Expression.NodeType?==?ExpressionType.Parameter)?{
????????????sb.Append(m.Member.Name);
????????????
return?m;
????????}
????????
throw?new?NotSupportedException(string.Format("The?member?'{0}'?is?not?supported",?m.Member.Name));
????}
}

?

?

?

對(duì)于實(shí)現(xiàn)了IQueryable的對(duì)象,在他們進(jìn)行的每一個(gè)操作(也就是調(diào)用實(shí)現(xiàn)這個(gè)接口的類(lèi)上的方法)其實(shí)都沒(méi)有立刻去執(zhí)行,而且把進(jìn)行的操作記錄下來(lái)了,放在一個(gè)稱(chēng)為Expression Tree表達(dá)式數(shù)的數(shù)據(jù)結(jié)構(gòu)中,然后再真正執(zhí)行的時(shí)候(就是調(diào)用Execute來(lái)執(zhí)行), QueryTranslator對(duì)象就遍歷表達(dá)式樹(shù),對(duì)操作進(jìn)行解析,例如linq to sql就是把表達(dá)式樹(shù)中操作解析為對(duì)數(shù)據(jù)庫(kù)進(jìn)行的操作,以sql語(yǔ)句的形式體現(xiàn)出來(lái).

?

?????? 當(dāng)把操作解析為了sql語(yǔ)句之后,就是用ADO.NET的方法來(lái)執(zhí)行SQL操作,然后通過(guò)反射,把ADO.NET執(zhí)行的結(jié)果轉(zhuǎn)換為數(shù)據(jù)實(shí)體。如下:???????

代碼 internal?class?ObjectReader<T>?:?IEnumerable<T>,?IEnumerable?where?T?:?class,?new()?{
????Enumerator?enumerator;
?

????
internal?ObjectReader(DbDataReader?reader)?{
????????
this.enumerator?=?new?Enumerator(reader);
????}
?

????
public?IEnumerator<T>?GetEnumerator()?{
????????Enumerator?e?
=?this.enumerator;
????????
if?(e?==?null)?{
????????????
throw?new?InvalidOperationException("Cannot?enumerate?more?than?once");
????????}
????????
this.enumerator?=?null;
????????
return?e;
????}
?

????IEnumerator?IEnumerable.GetEnumerator()?{
????????
return?this.GetEnumerator();
????}
?

????
class?Enumerator?:?IEnumerator<T>,?IEnumerator,?IDisposable?{
????????DbDataReader?reader;
????????FieldInfo[]?fields;
????????
int[]?fieldLookup;
????????T?current;
?

????????
internal?Enumerator(DbDataReader?reader)?{
????????????
this.reader?=?reader;
????????????
this.fields?=?typeof(T).GetFields();
????????}
?

????????
public?T?Current?{
????????????
get?{?return?this.current;?}
????????}
?

????????
object?IEnumerator.Current?{
????????????
get?{?return?this.current;?}
????????}
?

????????
public?bool?MoveNext()?{
????????????
if?(this.reader.Read())?{
????????????????
if?(this.fieldLookup?==?null)?{
????????????????????
this.InitFieldLookup();
????????????????}
????????????????T?instance?
=?new?T();
????????????????
for?(int?i?=?0,?n?=?this.fields.Length;?i?<?n;?i++)?{
????????????????????
int?index?=?this.fieldLookup[i];
????????????????????
if?(index?>=?0)?{
????????????????????????FieldInfo?fi?
=?this.fields[i];
????????????????????????
if?(this.reader.IsDBNull(index))?{
????????????????????????????fi.SetValue(instance,?
null);
????????????????????????}
????????????????????????
else?{
????????????????????????????fi.SetValue(instance,?
this.reader.GetValue(index));
????????????????????????}
????????????????????}
????????????????}
????????????????
this.current?=?instance;
????????????????
return?true;
????????????}
????????????
return?false;
????????}
?

????????
public?void?Reset()?{
????????}
?

????????
public?void?Dispose()?{
????????????
this.reader.Dispose();
????????}
?

????????
private?void?InitFieldLookup()?{
????????????Dictionary
<string,?int>?map?=?new?Dictionary<string,?int>(StringComparer.InvariantCultureIgnoreCase);
????????????
for?(int?i?=?0,?n?=?this.reader.FieldCount;?i?<?n;?i++)?{
????????????????map.Add(
this.reader.GetName(i),?i);
????????????}
????????????
this.fieldLookup?=?new?int[this.fields.Length];
????????????
for?(int?i?=?0,?n?=?this.fields.Length;?i?<?n;?i++)?{
????????????????
int?index;
????????????????
if?(map.TryGetValue(this.fields[i].Name,?out?index))?{
????????????????????
this.fieldLookup[i]?=?index;
????????????????}
????????????????
else?{
????????????????????
this.fieldLookup[i]?=?-1;
????????????????}
????????????}
????????}
????}
}

?

?

?????? 上面簡(jiǎn)單的介紹了如何實(shí)現(xiàn)linq to sql具體的實(shí)現(xiàn)代碼,大家可以自己過(guò)后慢慢的看或者參看我的另外的一個(gè)linq系列,現(xiàn)在我們繼續(xù)后面的話(huà)題。?

?????? 現(xiàn)在我們回到之前的話(huà)題:條件對(duì)象是否可以采用這種方式實(shí)現(xiàn)???????

?????? 大家看到上面的代碼Query<T>其中的T,和Execute方法的返回值。在上面的代碼中,如果T是User類(lèi),即,Query<User>,那么最后的Execute方法返回的一定會(huì)是User的集合。也就是說(shuō):Execute方法已經(jīng)對(duì)數(shù)據(jù)源(這里是數(shù)據(jù)庫(kù))進(jìn)行了操作,并且把結(jié)果以數(shù)據(jù)實(shí)體的形式已經(jīng)返回了,并且返回的數(shù)據(jù)實(shí)體的類(lèi)型就是T,例如User。

?????? 但是我們這里的要實(shí)現(xiàn)的條件對(duì)象只是想把條件構(gòu)造出來(lái),不是立刻去執(zhí)行。至于具體的執(zhí)行數(shù)據(jù)操作者(DataProvider)可以任意選擇的:使用ADO.NET方法,還是EF的方法,還是Nhibernate,都是可以配置的。如下:??????

代碼 ????public?List<User>?GetUserByAge()
????????{
????????????ICriteria
<User>?conditionPerson?=
???????????????CriteriaFactory.Create
<User>().Where(u?=>?u.Age?<?this.Age).OrderBy<string>(u?=>?u.Name).Skip(8).Take(8);
????????????
return?DataPortal.Query(conditionPerson);
????????}

???????

  上面的代碼中,Create方法就是實(shí)例化一個(gè)ICriteria<User>,此時(shí)我們想做的僅僅只是一件事:把在 ICriteria<User>上的操作記錄下來(lái)而已。然后把記錄下來(lái)的結(jié)果解析,解析的最終結(jié)果就是一條sql命令,然后再給不同的DataProvider去執(zhí)行。也就是說(shuō),在DataPortal內(nèi)部可以配置用什么方法來(lái)執(zhí)行數(shù)據(jù)操作:是直接使用ADO.NET執(zhí)行sql命令,還是把sql命令給Entity Framework...通過(guò)配置決定。如果ICriteria<T>是從IQueryable接口進(jìn)行了繼承,那么在ICriteria實(shí)現(xiàn)這個(gè)結(jié)果的過(guò)程中就必須要去數(shù)據(jù)庫(kù)中進(jìn)行執(zhí)行,因?yàn)镋xecute方法返回的是T的集合,而不是sql命令(字符串)。?

?????? 大家可能想到:那就在Execute方法中去實(shí)現(xiàn)不同的DataProvider,例如之前的例子在ObjectReader用ADO.NET實(shí)現(xiàn)了,那么也可以在ObjectReader中用EF實(shí)現(xiàn)數(shù)據(jù)操作。這個(gè)方法確實(shí)可以,也很不錯(cuò)。但是這個(gè)方法在分布式開(kāi)發(fā)中(特別是在WCF中)有一點(diǎn)的局限性。例如你有一個(gè)界面,上面可以有很多的選項(xiàng),如下:

?

?

  在服務(wù)接口那邊,你肯定不想定義N多差不多的接口方法:如

GetUserByName(string?username);

GetUserByEmail(
string?email);

?

  或者

GetUserByCondition(string?username,string?password,string?email?.....);

?

?  這樣都是很不靈活的,如果User的屬性減少了或者增多了,那么如果要在服務(wù)器那邊暴露的接口的方法也要修改,這樣終究是不好。如下采用下面的方法:?

GetUserByCondition(Critera?condition);

??

  其中,Critera是條件對(duì)象。那么我們?cè)诳蛻?hù)端就可以任意構(gòu)造條件對(duì)象,這個(gè)條件對(duì)象就把在它上面進(jìn)行的操作記錄下來(lái),然后統(tǒng)一的交給GetUserByCondition方法去服務(wù)器解釋并執(zhí)行。此時(shí),這個(gè)條件對(duì)象就是在客戶(hù)端生成的,而且這個(gè)條件對(duì)象此時(shí)是不用去數(shù)據(jù)庫(kù)中去執(zhí)行的。如果條件對(duì)象是從IQueryable接口繼承的,那么在客戶(hù)端構(gòu)造完條件對(duì)象之后,就要去數(shù)據(jù)庫(kù)中執(zhí)行了,如果再在ObjectReader搞個(gè)分布式調(diào)用,難度不說(shuō),也很別扭,這不是我們所要的。

?????? 所以,綜合上面的一些考慮,那么可以確定:條件對(duì)象不繼承IQueryable接口。但是我們又希望采用類(lèi)似linq的操作,那么只有自己實(shí)現(xiàn)了。?

  本篇就暫時(shí)寫(xiě)到這里,因?yàn)樘L(zhǎng)了,所以分為前篇和后篇發(fā)布,因?yàn)椴┛蛨@不能在一小時(shí)內(nèi)發(fā)兩篇,所以后篇將會(huì)在9點(diǎn)左右發(fā)布。希望大家見(jiàn)諒。

  版權(quán)為小洋和博客園所有,,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)標(biāo)明出處給作者。

?  http://www.cnblogs.com/yanyangtian

?

總結(jié)

以上是生活随笔為你收集整理的[原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(前篇)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。