日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

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

生活随笔

當(dāng)前位置: 首頁(yè) >

【问链-EOS公开课】第九课 EOS 数据库与持久化 API(二)

發(fā)布時(shí)間:2025/3/15 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【问链-EOS公开课】第九课 EOS 数据库与持久化 API(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上次的文章詳細(xì)講解了 EOS 數(shù)據(jù)庫(kù)的架構(gòu),本文將以官方示例為基礎(chǔ),詳解 EOS 數(shù)據(jù)庫(kù)的開(kāi)發(fā)實(shí)戰(zhàn)。

基本步驟

在智能合約里與 EOS 數(shù)據(jù)庫(kù)交互,首先要定義存儲(chǔ)的數(shù)據(jù):

定義對(duì)象:具體就是定義一個(gè) C++ 類(lèi)或者 C++ 結(jié)構(gòu)體,數(shù)據(jù)表就由一個(gè)個(gè)對(duì)象組成。
定義主鍵:在剛才的類(lèi)/結(jié)構(gòu)體中,定義一個(gè)const類(lèi)型的成員函數(shù)primary_key(),返回值必須為uint64_t類(lèi)型,返回值即為主鍵。
定義索引:EOS 數(shù)據(jù)表不光可以按照主鍵搜索數(shù)據(jù),還可以定義多達(dá) 16 種索引。而且索引鍵(Key)不止支持64位無(wú)符號(hào)整數(shù),還支持 128、256位整數(shù)以及雙精度、四精度浮點(diǎn)數(shù)。
為每個(gè)索引定義鍵提取器(key extractor)。

存儲(chǔ)數(shù)據(jù)定義好之后,就可以與數(shù)據(jù)庫(kù)交互了:

建立數(shù)據(jù)表:實(shí)例化 multi_index,建立數(shù)據(jù)表。
增刪數(shù)據(jù):使用emplace方法在表中添加數(shù)據(jù);使用erace方法刪除數(shù)據(jù)。
修改數(shù)據(jù):使用modify方法修改數(shù)據(jù)。
查詢(xún)數(shù)據(jù):使用get、find方法和其他迭代器操作查詢(xún)數(shù)據(jù)。

需求分析

我們參考 EOS 的官方示例,建立一個(gè)“汽車(chē)修理店”智能合約所需要的數(shù)據(jù)庫(kù)。數(shù)據(jù)庫(kù)服務(wù)的對(duì)象是維修技師和車(chē)主。每次車(chē)輛維修保養(yǎng)后,維修技師都可以添加本次維修服務(wù)的信息,可以更科學(xué)地管理每位客戶(hù)的車(chē)輛維修保養(yǎng)服務(wù)。而且維修技師和車(chē)主都可以更新車(chē)輛目前的里程,以便技師確定車(chē)輛是否應(yīng)該保養(yǎng)。我們需要一個(gè)數(shù)據(jù)表:維修數(shù)據(jù)表(service Table)。

建立數(shù)據(jù)對(duì)象

維修數(shù)據(jù)表中,每一條數(shù)據(jù)對(duì)象就是一次車(chē)輛維修保養(yǎng)的數(shù)據(jù),包含以下成員:

主鍵:因?yàn)閿?shù)據(jù)表主鍵必須是唯一的,所以無(wú)法用顧客的賬戶(hù)名作為主鍵(同一個(gè)顧客有多條維修記錄)。這里我們讓系統(tǒng)自動(dòng)生成主鍵。
顧客賬戶(hù):存儲(chǔ)每次維修服務(wù)的顧客賬戶(hù)名。
維修日期:每次維修服務(wù)的日期。
車(chē)輛里程:每次服務(wù)時(shí),車(chē)輛的里程信息。

我們還想方便的查詢(xún)每個(gè)顧客的維修記錄,所以需要一個(gè)以顧客賬戶(hù)名為鍵(Key)的索引。

這樣我們就得到了 service_rec 結(jié)構(gòu)體:

struct service_rec {uint64_t pkey; // 主鍵account_name customer; // 顧客賬戶(hù)uint32_t service_date; // 維修日期uint32_t odometer; // 車(chē)輛里程//設(shè)置主鍵auto primary_key()const { return pkey; }//設(shè)置索引account_name get_customer()const { return customer; }//SERIALIZE 宏可以幫助提高編譯速度EOSLIB_SERIALIZE( service_rec, (pkey)(customer)(service_date)(odometer) ) };

建立數(shù)據(jù)表

下面就可以建立數(shù)據(jù)表了,首先,multi_index是個(gè)模板類(lèi):(對(duì) C++ 模板不熟悉的可以百度一下)

eosio::multi_index <uint64_t TableName, typename T, typename... Indices>

我們需要填入以下multi_index的模板參數(shù):

TableName為數(shù)據(jù)表名稱(chēng),12字符以?xún)?nèi),只能使用小寫(xiě)字母,數(shù)字1-5,小數(shù)點(diǎn)“.”。
T為數(shù)據(jù)對(duì)象類(lèi)型,這里就是我們定義的service_rec結(jié)構(gòu)體。
Indices為索引列表,最多十六個(gè)。為了降低開(kāi)發(fā)難度,官方推薦使用const_mem_fun模板,大家可以模仿官方的做法:

按照需求,我們這樣設(shè)置multi_index的模板參數(shù):

using service_table_type = multi_index<service/*<-數(shù)據(jù)表名稱(chēng)*/, service_rec,/*<-數(shù)據(jù)對(duì)象類(lèi)型*//*設(shè)置索引->*/indexed_by< N(bycustomer), const_mem_fun<service_rec, account_name, &service_rec::get_customer> >

這里并沒(méi)有實(shí)例化multi_index,只是將填入相應(yīng)模板參數(shù)的multi_index設(shè)置了一個(gè)別名:service_table_type。依然,對(duì)這里的做法不熟悉的可以看一下 C++ 模板類(lèi)以及 C++ 的 using 關(guān)鍵字。

下面我們實(shí)例化multi_index,構(gòu)造函數(shù)需要兩個(gè)參數(shù):

multi_index( uint64_t code, uint64_t scope )

其中,code為數(shù)據(jù)表的擁有者,scope為數(shù)據(jù)表的細(xì)分名稱(chēng)。這里有兩種理解,一種理解是不同的 scope 就是不同的數(shù)據(jù)表,也就是說(shuō),在同一個(gè)賬戶(hù)下,存在著TableName相同的多個(gè)數(shù)據(jù)表,他們的scope互不相同;另一種理解:scope表示了同一個(gè)數(shù)據(jù)表的不同部分,互相獨(dú)立讀寫(xiě)。這兩種理解的結(jié)果是一樣的,就是唯一確定一個(gè)數(shù)據(jù)表需要三個(gè)參數(shù):TableName,code,scope。

實(shí)例化multi_index:

service_table_type service_table( current_receiver(), mechanic );

上面的code = current_receiver(),表示當(dāng)前的智能合約,即“汽車(chē)維修店合約”。如果這里的code為其他合約,那么說(shuō)明這個(gè)multi_index指向了其他賬戶(hù)名下的數(shù)據(jù)表,在本合約中就只能進(jìn)行讀取操作了。scope = mechanic表明實(shí)例化的這個(gè)multi_index指向了細(xì)分名稱(chēng)為mechanic(以維修技師賬戶(hù)命名)的數(shù)據(jù)表。

我們所建立的數(shù)據(jù)表結(jié)構(gòu)如下圖所示。

操作數(shù)據(jù)

一般數(shù)據(jù)庫(kù)的基本操作是增、刪、改、查,EOS 數(shù)據(jù)庫(kù)當(dāng)然也具有這些功能。

新增數(shù)據(jù)

新增數(shù)據(jù)需要用到multi_index的emplace方法:

const_iterator emplace( unit64_t payer, Lambda&& constructor )

其中的payer參數(shù)位儲(chǔ)存空間支付賬戶(hù),也就是由誰(shuí)來(lái)提供新加入的這個(gè)數(shù)據(jù)對(duì)象的存儲(chǔ)空間,這里填入維修技師mechanic賬戶(hù)。constructor是個(gè) Lambda 表達(dá)式,也叫匿名函數(shù),是向emplace方法傳入了一個(gè)構(gòu)造函數(shù),用來(lái)構(gòu)造這個(gè)新的數(shù)據(jù)對(duì)象。

service_table.emplace(mechanic,/*<-儲(chǔ)存空間支付賬戶(hù)*/ [&]( auto& s_rec )/*<-匿名函數(shù)*/ {s_rec.pkey = service_table.available_primary_key(); /*<-系統(tǒng)生成可用主鍵*/ //匿名函數(shù)體s_rec.customer = eosio::chain::string_to_name(customer_name); //匿名函數(shù)體s_rec.service_date = service_date; //匿名函數(shù)體s_rec.odometer = odometer; //匿名函數(shù)體 });

其中的customer_name、service_date、odometer要在實(shí)際開(kāi)發(fā)時(shí)使用有意義的變量。

查詢(xún)數(shù)據(jù)

由于service_table數(shù)據(jù)表的主鍵是沒(méi)有意義的,所以我們需要使用bycustomer索引來(lái)根據(jù)顧客賬戶(hù)名(customer)查詢(xún)數(shù)據(jù)。

auto customer_index = service_table.template get_index<N(bycustomer)>();

這樣我們就得到了bycustomer索引,我們可以使用索引的find方法來(lái)按照索引查找特定customer的數(shù)據(jù)對(duì)象。

//建立要查找的賬戶(hù),注意這里的customer_name要使用有意義的字符串

account_name customer_acct = eosio::chain::string_to_name(customer_name);

//使用find方法查找數(shù)據(jù),使cust_itr(迭代器)指向所需數(shù)據(jù)

auto cust_itr = customer_index.find(customer_acct);

如果沒(méi)有查找到,cust_itr(迭代器)就是service_table.end(),也就是搜索到最后也沒(méi)有找到對(duì)應(yīng)的數(shù)據(jù)。如果查找成功,cust_itr(迭代器)就會(huì)指向所需的數(shù)據(jù)對(duì)象。

之后,可以使用下面的代碼可以遍歷數(shù)據(jù)表中所有我們所需的條目。(因?yàn)轭櫩唾~戶(hù)名不是唯一的,用find方法會(huì)找到符合條件的第一條數(shù)據(jù))

while (cust_itr != service_table.end() /<-判斷迭代器位置/&& cust_itr->customer == customer_acct/<-判斷數(shù)據(jù)是否符合/) {

// 業(yè)務(wù)邏輯,對(duì)數(shù)據(jù)進(jìn)行處理cust_itr++;//迭代器自增,指向下一條數(shù)據(jù)

}

修改數(shù)據(jù)

在迭代器指向數(shù)據(jù)后,可以對(duì)數(shù)據(jù)進(jìn)行修改,使用modify方法:

service_table.modify(cust_itr,/<-迭代器/, mechanic, /<-儲(chǔ)存空間支付賬戶(hù)/ [&]( auto& s_rec )/<-匿名函數(shù)/

{s_rec.customer = new_customer; //匿名函數(shù)體s_rec.service_date = new_service_date; //匿名函數(shù)體s_rec.odometer = new_odometer; //匿名函數(shù)體 });

匿名函數(shù)中的new_customer、new_service_date、new_odometer請(qǐng)使用有意義的變量。也可以只修改其中部分變量。

刪除數(shù)據(jù)

在迭代器指向數(shù)據(jù)后,可以對(duì)數(shù)據(jù)進(jìn)行刪除,使用erase方法:

service_table.erase( cust_itr/*<-迭代器*/ );

至此,帶領(lǐng)大家了初步解了 EOS 數(shù)據(jù)庫(kù)開(kāi)發(fā)的思路與方法,EOS 數(shù)據(jù)庫(kù)還有很多 API 可以供智能合約使用,大家可以查閱官方 Wiki:
https://github.com/EOSIO/eos/wiki/Persistence-API

總結(jié)

以上是生活随笔為你收集整理的【问链-EOS公开课】第九课 EOS 数据库与持久化 API(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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