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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

iBatis.Net(C#)数据库查询

發(fā)布時間:2024/9/20 C# 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iBatis.Net(C#)数据库查询 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

引用請注明http://www.cnblogs.com/13590/archive/2013/03/14/2958735.html?

摘要:查詢是數(shù)據(jù)庫SQL語言的核心,本文介紹了通過iBatis.Net對數(shù)據(jù)庫的簡單查詢、條件查詢、動態(tài)查詢和多表查詢。

關鍵詞:iBatis.Net;動態(tài)查詢;多表查詢;數(shù)據(jù)映射

查詢是數(shù)據(jù)庫SQL語言的核心,SQL語言只提供唯一一個用于數(shù)據(jù)庫查詢的語句,即SELECT語句。用于表達SQL查詢的SELECT語句是功能最強也是最復雜的SQL語句。而在實際的項目開發(fā)過程中,查詢占了一個很大的比重,通常衡量一個框架的好壞也很大程度上取決于該框架對查詢的靈活性和效率。本節(jié)介紹在iBatis.Net中提供的數(shù)據(jù)庫查詢方式。

在上節(jié)建立的項目文件中新添加Maps/Test3.xml和Test3.aspx項,分別記錄XML數(shù)據(jù)映射信息和相應的程序調用信息。

1、簡單查詢

獲取一個表的內容,如獲取DEAN.SYSUSER表的用戶信息,XML數(shù)據(jù)映射配置信息為:

<selectid="SelectSysuser"resultMap="SysuserResult">

SELECT * FROM DEAN.SYSUSER

</select>

調用代碼為:

protectedvoid?Button1_Click(object?sender,?EventArgs?e)

{

//簡單查詢

try

{

ISqlMapper?mapper =?Mapper.Instance();?//得到ISqlMapper實例

IList<iBatisTest.Domain.Sysuser> plist = mapper.QueryForList<iBatisTest.Domain.Sysuser>("Test3Map.SelectSysuser",null);//調用QueryForList方法

if?(plist !=?null?&& plist.Count > 0)

{

GridView1.DataSource = plist;

GridView1.DataBind();

}

Label1.Text =?"簡單查詢成功";

}

catch?(Exception?ex)

{

Label1.Text = ex.Message;

}

}

這種查詢結果返回的是整張表的所有記錄,無需傳入查詢參數(shù),在調用QueryForList方法時把參數(shù)置為null??紤]到系統(tǒng)的效率,在實際開發(fā)中,對記錄數(shù)少的小表才使用。

2、條件查詢

根據(jù)條件來查詢結果,條件可以是一個或者多個。這種方式在實際查詢中被廣泛使用,是應用最多的一種查詢。如根據(jù)登錄用戶名查詢該用戶信息,數(shù)據(jù)映射配置信息為:

<selectid="SelectSysuserByUserName"parameterClass="string"resultMap="SysuserResult">

SELECT * FROM DEAN.SYSUSER WHERE LOGINNAME=#value#

</select>

iBatis.Net通過使用#或者$符號來占位,即標識參數(shù)。在XML數(shù)據(jù)映射文件的SQL語句中引入?yún)?shù)有2種方式,一種是內聯(lián)參數(shù)方式,即使用parameterClass,如上面的配置就采用這種方式。一種是參數(shù)映射方式,使用parameterMap。采用內聯(lián)方式時,允許我們把屬性名稱、屬性類型、空置方式配置在SQL語句中。

使用內聯(lián)參數(shù)方式時,傳入的參數(shù)有3種類型,分別為:

(1)基本參數(shù)類型,很多SQL語句在查詢時只接受一個參數(shù),如int、string,使用#value#來引用,這個value是關鍵字,不可變,上面的示例就采用這種方式。也可以采用#keyName#來引用,keyName為鍵名,注意要區(qū)分大小寫。

(2)字典類型參數(shù),使用IDictionary類型的對象作為參數(shù)。通??梢允褂肏ashtable。如上面配置可修改為

<select id="SelectSysuserByUserName" parameterClass="System.Collections.IDictionary" resultMap="SysuserResult">

SELECT * FROM DEAN.SYSUSER WHERE LOGINNAME=#LOGINNAME#

</select>

(3)對象類型參數(shù),可以是一個類或者是哈希表Hashtable,在使用哈希表時,某一個鍵值可以是一個列表List類型。

調用代碼如下:

protectedvoid?Button2_Click(object?sender,?EventArgs?e)

{

//條件查詢

try

{

string?UserName = TextBox1.Text;//獲取查詢參數(shù)用戶名

ISqlMapper?mapper =?Mapper.Instance();?//得到ISqlMapper實例

IList<iBatisTest.Domain.Sysuser> plist = mapper.QueryForList<iBatisTest.Domain.Sysuser>("Test3Map.SelectSysuserByUserName", UserName);//調用QueryForList方法

if?(plist !=?null?&& plist.Count > 0)

{

GridView1.DataSource = plist;

GridView1.DataBind();

}

Label1.Text =?"條件查詢成功";

}

catch?(Exception?ex)

{

Label1.Text = ex.Message;

}

}

如果采用字典類型參數(shù)傳入,只需要把調用中的參數(shù)修改為:

Hashtable hash = new Hashtable();//聲明哈希表

hash.Add("LOGINNAME ", TextBox1.Text); //獲取查詢參數(shù)用戶名

3、動態(tài)查詢

iBatis.Net提供查詢的靈活性主要體現(xiàn)在支持動態(tài)查詢上,即可以動態(tài)的生成SQL語句。也只有掌握好動態(tài)查詢,才能充分的感受iBatis框架所帶來的便捷和高效。這也是很多軟件公司和開發(fā)人員選擇該框架的重要原因。

在開發(fā)中經(jīng)常遇到這種查詢,當用戶沒有輸入查詢條件時查詢所有記錄,如果用戶輸入了查詢條件將根據(jù)查詢條件進行查詢。比如上面提到的條件查詢,如果沒有輸入用戶名信息將返回所有用戶信息。這個時候就需要用到動態(tài)查詢,根據(jù)參數(shù)值是否為空,生成兩條不同的SQL語句。XML數(shù)據(jù)映射配置信息為:

<selectid="SelectSysuserDynamic1"parameterClass="System.Collections.IDictionary"resultMap="SysuserResult">

<![CDATA[?SELECT * FROM DEAN.SYSUSER?]]>

<dynamicprepend="WHERE">

<isNotEmptyprepend="AND"property="LOGINNAME">

<![CDATA[?LOGINNAME = #LOGINNAME#?]]>

</isNotEmpty>

</dynamic>

</select>

dynamic元素用來區(qū)分SQL語句的動態(tài)部分,dynamic是一個可選項,它中間可以包含任意數(shù)據(jù)的條件元素。上面的配置信息會根據(jù)輸入?yún)?shù)LOGINNAME的值是否為空生成兩條SQL語句。如果為空SELECT * FROM DEAN.SYSUSER,如果不為空SELECT * FROM DEAN.SYSUSER WHERE LOGINNAME = #LOGINNAME#。

調用程序代碼為:

protectedvoid?Button3_Click(object?sender,?EventArgs?e)

{

//動態(tài)查詢1

try

{

Hashtable?hash =?newHashtable();//聲明哈希表

hash.Add("LOGINNAME", TextBox2.Text);?//獲取查詢參數(shù)用戶名

ISqlMapper?mapper =?Mapper.Instance();?//得到ISqlMapper實例

IList<iBatisTest.Domain.Sysuser> plist = mapper.QueryForList<iBatisTest.Domain.Sysuser>("Test3Map.SelectSysuserDynamic1", hash);//調用QueryForList方法

if?(plist !=?null?&& plist.Count > 0)

{

GridView1.DataSource = plist;

GridView1.DataBind();

}

Label1.Text =?"動態(tài)查詢1成功";

}

catch?(Exception?ex)

{

Label1.Text = ex.Message;

}

}

}

在iBatis.Net中,動態(tài)查詢的條件元素包含以下幾種:二元條件元素、一元條件元素和其他條件元素:

3.1二元條件元素

將一個屬性值和靜態(tài)值或另一個屬性值比較,如果條件為真,元素將被包容在查詢SQL語句中。

二元條件元素的屬性:

perpend——可被覆蓋的SQL語句組成部分,添加在語句的前面,該屬性為可選。

property——是比較的屬性,該屬性為必選。

compareProperty——另一個用于和前者比較的屬性(必選或選擇compareValue屬性)

compareValue——用于比較的值(必選或選擇compareProperty屬性)

二元條件元素為:

<isEqual>

比較屬性值和靜態(tài)值或另一個屬性值是否相等,如果相等則查詢條件有效。如:

<isEqual prepend="AND" property="status" compareValue="Y">

MARRIED = 'TRUE'

</isEqual>

<isNotEqual>

比較屬性值和靜態(tài)值或另一個屬性值是否不相等,如果不相等則查詢條件有效。

<isGreaterThan>

比較屬性值是否大于靜態(tài)值或另一個屬性值,如果大于則查詢條件有效。如:

<isGreaterThan prepend="AND" property="age" compareValue="18">

ADOLESCENT = 'FALSE'

</isGreaterThan>

<isGreaterEqual>

比較屬性值是否大于等于靜態(tài)值或另一個屬性值,如果相等等于則查詢條件有效。

<isLessThan>

比較屬性值是否小于靜態(tài)值或另一個屬性值,如果小于則查詢條件有效。

<isLessEqual>

比較屬性值是否小于等于靜態(tài)值或另一個屬性值。如:

<isLessEqual prepend="AND" property="age" compareValue="18"> ADOLESCENT = 'TRUE' </isLessEqual>

二元條件元素多用在數(shù)字的區(qū)間選擇上,如年齡、價格、面積等選擇上面,也可以用在日期、字符串等類型的比較。如只顯示ID<=10的指定ID的用戶信息,如果輸入值大于10則顯示全部用戶信息。XML數(shù)據(jù)映射配置信息為:

<selectid="SelectSysuserDynamic2"parameterClass="System.Collections.IDictionary"resultMap="SysuserResult">

<![CDATA[?SELECT * FROM DEAN.SYSUSER?]]>

<dynamicprepend="WHERE">

<isLessEqualprepend="AND"property="USERID"compareValue="10">

USERID = #USERID#

</isLessEqual>

</dynamic>

</select>

調用代碼為:

protectedvoid?Button4_Click(object?sender,?EventArgs?e)

{

//動態(tài)查詢2:二元條件元素查詢

try

{

Hashtable?hash =?newHashtable();//聲明哈希表

int?ID = 0;

if?(!string.IsNullOrWhiteSpace(TextBox3.Text))

{

ID =?Convert.ToInt32(TextBox3.Text);

}

hash.Add("USERID", ID);?//獲取查詢參數(shù)

ISqlMapper?mapper =?Mapper.Instance();?//得到ISqlMapper實例

IList<iBatisTest.Domain.Sysuser> plist = mapper.QueryForList<iBatisTest.Domain.Sysuser>("Test3Map.SelectSysuserDynamic2", hash);//調用QueryForList方法

if?(plist !=?null?&& plist.Count > 0)

{

GridView1.DataSource = plist;

GridView1.DataBind();

}

else

{

GridView1.DataSource =?null;

GridView1.DataBind();

}

Label1.Text =?"動態(tài)查詢2成功";

}

catch?(Exception?ex)

{

Label1.Text = ex.Message;

}

}

3.2一元條件元素

一元條件元素檢查屬性的狀態(tài)是否符合特定的條件。即檢查屬性值是否滿足條件,如果滿足則查詢條件有效。

一元條件元素的屬性和二元條件元素一樣,具有prepend和property屬性,其中property為必選屬性。

一元條件元素為:

<isPropertyAvailable>

檢查是否存在該屬性。

<isNotPropertyAvailable>

檢查是否不存在該屬性。

<isNull>

檢查屬性是否為null。

<isNotNull>

檢查屬性是否不為null。

<isEmpty>

檢查屬性是否為空,屬性的數(shù)據(jù)類型為Collection、String 時檢查是否為null或空,即是否為""或size() < 1。如:

<isNotEmpty prepend="AND" property="firstName" >

FIRST_NAME=#firstName#

</isNotEmpty>

<isNotEmpty>

檢查屬性是否不為空,檢查方式同上。

比如下面的配置例子:

<selectid="SelectSysuserDynamic3"resultMap="SysuserResult"parameterClass="System.Collections.IDictionary">

<![CDATA[?SELECT * FROM DEAN.SYSUSER?]]>

<dynamicprepend="WHERE">

<isPropertyAvailableproperty="SEX">

<isNotNullproperty="SEX"prepend="AND">

SEX=#SEX#

</isNotNull>

</isPropertyAvailable>

<isPropertyAvailableproperty="STATUS">

<isNotNullproperty="STATUS"prepend="AND">

STATUS=#STATUS#

</isNotNull>

</isPropertyAvailable>

</dynamic>

</select>

先判斷傳入?yún)?shù)集是否有SEX參數(shù),如果沒有則不執(zhí)行SEX=#SEX#查詢條件,再判斷該參數(shù)是否為null,不為null才執(zhí)行查詢條件。isPropertyAvailable元素最大的好處是,如果輸入的參數(shù)集不包括設置的參數(shù)時程序不會報錯,直接跳過該元素設置內容。

3.3其他元素條件

其他元素條件有兩個元素,一個為ParameterPresent,該元素檢查參數(shù)對象是否存在,一個為Iterate,該元素為遍歷整個集合。

(1)?ParameterPresent

ParameterPresent元素屬性只有prepend一個屬性,表示可被覆蓋的SQL語句組成部分,添加在語句的前面,為可選屬性。

<isParameterPresent>

檢查是否存在參數(shù)對象,即如果參數(shù)類不為NULL則查詢條件有效。如:

<isParameterPresent prepend="AND"> EMPLOYEE_TYPE = #empType# </isParameterPresent>

<isNotParameterPresent>

檢查是否不存在參數(shù)對象,如:

<isNotParameterPresent prepend="AND"> EMPLOYEE_TYPE = 'DEFAULT' </isNotParameterPresent>

(2) Iterate:遍歷整個集合元素,為List集合中的元素重復元素體的內容。

Iterate的屬性:

prepend——可被覆蓋的SQL語句組成部分,添加在語句的前面,該屬性為可選。

property——類型為List的用于遍歷的元素屬性,該屬性為必選。

open——整個遍歷內容體開始的字符串,用于定義括號,該屬性為可選。

close ——整個遍歷內容體結束的字符串,用于定義括號,該屬性為可選。

conjunction——每次遍歷內容之間的字符串,用于定義AND或OR,該屬性為可選。

<iterate>

遍歷類型為List的元素。如:

<iterate prepend="AND" property="UserNameList"

open="(" close=")" conjunction="OR">

username=#UserNameList[]#

</iterate>

注意:使用<iterate>時,在List元素名后面包括方括號[]非常重要,方括號[]將對象標記為List,以防解析器簡單地將List輸出成String。

Iterate元素在生成sql語句時,標簽中的內容是循環(huán)生成的,如上面的例子將會生成語句:(username=xxx1 or username=xxx2 or username=xxx 3)。該元素也經(jīng)常用來動態(tài)生成In查詢條件,如id in (xx1,xx2,xx3,.....),括號中的(包括括號)都由該元素標簽生成。

比如下面的配置例子:

<selectid="SelectSysuserDynamic4"resultMap="SysuserResult"parameterClass="System.Collections.IDictionary">

<![CDATA[?SELECT * FROM DEAN.SYSUSER?]]>

<dynamicprepend="?WHERE">

<isPropertyAvailableproperty="SEX">

<isNotNullproperty="SEX"prepend="AND">

SEX=#SEX#

</isNotNull>

</isPropertyAvailable>

<isNotNullprepend="And"property="USERIDLIST">

USERID in

<iterateproperty="USERIDLIST"open="("close=")"conjunction=",">

#USERIDLIST[]#

</iterate>

</isNotNull>

</dynamic>

</select>

調用代碼為:

protectedvoid?Button6_Click(object?sender,?EventArgs?e)

{

//動態(tài)查詢2:其它元素條件,Iterate

try

{

Hashtable?hash =?newHashtable();//聲明哈希表

string?sex =?"男";

hash.Add("SEX", sex);

List<int> IDS =?newList<int>();//聲明List對象

IDS.Add(1);

IDS.Add(2);

IDS.Add(3);

hash.Add("USERIDLIST", IDS);

ISqlMapper?mapper =?Mapper.Instance();?//得到ISqlMapper實例

IList<iBatisTest.Domain.Sysuser> plist = mapper.QueryForList<iBatisTest.Domain.Sysuser>("Test3Map.SelectSysuserDynamic4", hash);//調用QueryForList方法

if?(plist !=?null?&& plist.Count > 0)

{

GridView1.DataSource = plist;

GridView1.DataBind();

}

else

{

GridView1.DataSource =?null;

GridView1.DataBind();

}

Label1.Text =?"動態(tài)查詢4成功";

}

catch?(Exception?ex)

{

Label1.Text = ex.Message;

}

}

系統(tǒng)會根據(jù)配置信息動態(tài)的生成In查詢條件,最終動態(tài)生成的SQL語句為:SELECT * FROM DEAN.SYSUSER AND SEX='男' And USERID in (1,2,3)。

4、多表查詢

前面講到的示例都是從一個表中查詢記錄,獲取的結果也是單個對象。事實上在程序開發(fā)中,經(jīng)常需要對多個表進行組合查詢,返回的結果也是復雜對象。如查詢用戶權限信息,就需要關聯(lián)用戶表和權限表。

向數(shù)據(jù)庫添加系統(tǒng)權限表SysUserRight,腳本如下:

CREATE TABLE DEAN.SYSUSERRIGHT

(

ID NUMBER(10,0) NOT NULL ENABLE,

USERID NUMBER(10,0) NOT NULL ENABLE,

RIGHTID NUMBER(10,0) NOT NULL ENABLE,

constraint PK_SYSUSERRIGHT primary key (ID)

);

comment on column DEAN.SYSUSERRIGHT.ID is 'ID';

comment on column DEAN.SYSUSERRIGHT.USERID is '用戶ID';

comment on column DEAN.SYSUSERRIGHT.RIGHTID is '權限ID';

有兩種方式來處理這種多表查詢,一種是參照單表查詢,根據(jù)返回結果定制一個新類,或者直接設置返回參數(shù)為Hashtable表。如:

<selectid="MultiTable1"resultClass="Hashtable"?>

SELECT A.*,B.RIGHTID FROM DEAN.SYSUSER A,DEAN.SYSUSERRIGHT B WHERE A.USERID=B.USERID

</select>

通過用戶ID(USERID)關聯(lián)用戶表(SYSUSER)和系統(tǒng)權限表(SYSUSERRIGHT)查詢出用戶信息及對應的權限信息,直接返回一個Hashtable表,記錄了相應的信息。

第二種方式是利用iBatis的復雜屬性來實現(xiàn),在Sysuser類新增一個屬性:

///<summary>

///多表查詢新增權限屬性

///</summary>

privateint?_rightid;

publicint?Rightid

{

get?{?return?_rightid; }

set?{_rightid =?value;}

}

修改配置文件信息,在resultMaps部分增加一個結果映射信息,唯一號為UserRightResult,它繼承于Test3Map.SysuserResult結果映射,增加的配置信息如下:

<resultMapid="UserRightResult"class="Sysuser"extends="Test3Map.SysuserResult">

<resultproperty="<spansstyle="color:blue; Rightid"column="USERID=USERID"select="Test3Map.SelectSysuserRight"?/>

</resultMap>

在statements節(jié)加入如下信息:

<statementid="SelectSysuserRight"parameterClass="int"resultClass="int">

SELECT RIGHTID FROM DEAN.SYSUSERRIGHT WHERE USERID= #USERID#

</statement>

<selectid="MultiTable2"parameterClass="int"resultMap="UserRightResult">

SELECT * FROM DEAN.SYSUSER ORDER BY USERID

</select>

通過XML配置文件中resultMap的result使用"select"進行一種迭代查詢,也就是將<result property="Rightid" column="USERID=USERID" select="Test3Map.SelectSysuserRight" />中column指定的一項或多項作為參數(shù)(USERID=USERID),傳入并執(zhí)行指定的select語句SelectSysuserRight,并將查詢結果賦給property=" Rightid ",從而實現(xiàn)多表查詢。

該例子中實現(xiàn)的是1:1的關系查詢,如果是1:n的關系查詢,只需要Sysuser類增加的屬性修改為IList類型。Statements節(jié)點"SelectSysuserRight"的返回類修改為resultClass=" SysuserRightResult"。

通過iBatis復雜屬性,可以非常方便的實現(xiàn)多表查詢,但這個方法給我們帶來便利的同時,也帶來了兩個問題。首先,創(chuàng)建包含大量對象的列表可能會消耗大量的內存。其次,這種方法會導致數(shù)據(jù)庫的I/O問題,其原因就是所謂的"N+1"查詢現(xiàn)象。對于主從表(也稱為父子表)的查詢,特別容易產(chǎn)生N+1查詢問題,N+1查詢問題是由于試圖加載多個父記錄(比如User)的子記錄(Right)而引起的。在查詢父記錄時,只需要1條語句,假設返回N條記錄,那么就需要再執(zhí)行N條語句來查詢子記錄,引發(fā)所謂的"N+1查詢"。

解決N+1查詢問題可以通過延遲加載(lazy loading)來實現(xiàn),它將加載過程打散為一些更小的過程。在父子表查詢過程中,對子表的查詢往往不需要和父表一起加載,例如,系統(tǒng)的用戶管理,打開一個用戶信息頁面時顯示的是用戶信息列表,當點擊一個用戶時,才需要加載該用戶的權限信息。這種情況就特別適合使用延遲加載,每次都僅查詢一個列表。使用延遲加載的時候還需要特別注意,使用的動態(tài)代理的對象的所有方法和屬性都必須是virtual類型。

要實現(xiàn)延遲加載,只需要在配置文件里面加入lazyLoad="true"屬性就可以了。通過延遲加載,它能提高查詢的效率,但并沒有真正解決數(shù)據(jù)庫I/O問題,在最壞的情況下,它對數(shù)據(jù)庫的訪問次數(shù)與非延遲加載的時候是一樣的。如何真正解決N+1查詢問題呢?iBatis提供了連接語句(join)方式來完全避免N+1查詢的出現(xiàn)。

修改配置文件信息,在resultMaps部分增加如下配置:

<resultMapid="SysuserRightResult"class="SysuserRight">

<resultproperty="ID"column="ID"/>

<resultproperty="Userid"column="USERID"?/>

<resultproperty="Rightid"column="RIGHTID"/>

</resultMap>

<resultMapid="SysuserJoinResult"class="SysuserJoin"extends="Test3Map.SysuserResult"groupBy="Userid">

<resultproperty="RightList"resultMapping="Test3Map.SysuserRightResult"?/>

</resultMap>

這個配置使用了relultMap的resultMapping屬性,該屬性用在如果一個數(shù)據(jù)類的屬性本身不是基元數(shù)據(jù)類型,而是一個復雜數(shù)據(jù)類型的場景。這個時候就不能用一個簡單的result元素來表示,必須給他一個完整的resultMap。resultMapping的值指明RightList屬性由結果映射集SysuserRightResult所表示的復雜數(shù)據(jù)類型表示。因為用戶和權限信息是一對多的關系,在主表的結果映射上加入groupBy="Userid"屬性。

注意用戶類SysuserJoin的權限屬性RightList的定義,它是由權限類SysuserRight組成的一個列表。RightList定義如下:

///多表查詢新增權限列表屬性

privateIList<SysuserRight> _rightlist;

publicIList?<SysuserRight> RightList

{

get?{?return?_rightlist; }

set?{ _rightlist =?value; }

}

在statements節(jié)加入如下信息

<selectid="MultiTable3"resultMap="SysuserJoinResult"?>

select A.*,B.* FROM DEAN.SYSUSER A LEFT JOIN DEAN.SYSUSERRIGHT B ON A.USERID=B.USERID?</select>

再通過程序的調用,就不會出現(xiàn)N+1查詢問題。

總結

以上是生活随笔為你收集整理的iBatis.Net(C#)数据库查询的全部內容,希望文章能夠幫你解決所遇到的問題。

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