EOS開發教程(4.2.2)數據持久化

in #eos4 years ago

void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) { require_auth( user ); }
前面我們配置了壹個多索引表:address_index。要想把壹個表實例化,需要提供兩個參數:

  1. 第壹個參數:code,它指定了這個表的所有者。作為所有者,那個帳號需要支付存儲成本。而且,只有這個帳號能修改或刪除這個表的數據,除非指定了其他的帳號來支付。這裏我們使用 get_self()函數,這個函數會傳遞這個合約的名字。
  2. 第二個參數:scope,它保證了這個表在這個合約內的是唯壹的。在本例中,由於我們只有壹個表,我們可以使用get_first_receiver()返回的值。get_first_receiver是這個合約被部署到的帳號的帳號名字。
    註意,我們使用scope在壹個多索引表裏從邏輯上區分不同的表(參看eosio.token合約做例子)。最初,scope用來區分表狀態,從而在子表中實現並行計算。然而,現在跨區塊鏈溝通的優先級比並行計算的優先級更高。由此,scope現在只用來在邏輯上區分表,就像eosio.token例子中的壹樣。
    void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) { require_auth( user ); address_index addresses(get_self(), get_first_receiver().value); }
    接著,查詢叠代器,把它設為壹個變量,因為將來會多次用到它。
    void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) { require_auth( user ); address_index addresses(get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); }
    Ok,現在把表實例化了,安全性也得到了保證。接下來,就來寫創建或修改表功能的代碼。
    首先,檢查看看表中是否已經存在壹個特定的用戶了。要做到這點,我們使用表的find 方法,把user參數傳遞給它。Find方法會返回壹個叠代器。使用這個叠代器對end方法結果進行測試。End方法是null方法的別名。
    void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) { require_auth( user ); address_index addresses(get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); if( iterator == addresses.end() ) { //The user isn’t in the table } else { //The user is in the table } }
    使用多索引方法emplace在表中創建壹條記錄。這個方法接收兩個參數,這條記錄的payer:支付存儲成本的用戶,以及壹個回調函數。
    Emplace方法的回調函數必須使用壹個lamba函數來創建壹個引用。在方法體裏把提供給upsert的值賦給行,當作行的值。
    void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) { require_auth( user ); address_index addresses(get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); if( iterator == addresses.end() ) { addresses.emplace(user, [&]( auto& row ) { row.key = user; row.first_name = first_name; row.last_name = last_name; row.street = street; row.city = city; row.state = state; }); } else { //The user is in the table } }
    接下來,處理upsert函數中的修改或更新部分。使用modify函數,傳遞幾個參數:
    · 之前定義的叠代器,目前設置為調用這個action時聲明的user。
    · 支付者,支付這行的存儲成本的用戶。
    · 回調函數,由它真正執行修改工作。
    void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) { require_auth( user ); address_index addresses(get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); if( iterator == addresses.end() ) { addresses.emplace(user, [&]( auto& row ) { row.key = user; row.first_name = first_name; row.last_name = last_name; row.street = street; row.city = city; row.state = state; }); } else { addresses.modify(iterator, user, [&]( auto& row ) { row.key = user; row.first_name = first_name; row.last_name = last_name; row.street = street; row.city = city; row.state = state; }); } }
    現在addressbook合約有了壹個功能完整的action,它能讓壹個用戶在表中創建壹行記錄,如果該記錄之前不存在的話,如果它已經存在,用戶可以修改它。
    Step 8: 從表中刪除記錄
    跟之前的步驟類似,在addressbook中創建壹個公共方法,記得包含ABI聲明,以及壹個 require_auth用來驗證action的參數uer,確保只有記錄的所有者才有權限修改他們的帳號。
    void erase(name user){ require_auth(user); }
    實例化表。在addressbook中每個帳號只有壹條記錄。使用find方法設置叠代器。
    ... void erase(name user){ require_auth(user); address_index addresses(get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); } ...
    合約不能刪除壹條不存在的記錄,所以,在進行下壹步操作之前先檢查看該記錄是否真的存在。
    ... void erase(name user){ require_auth(user); address_index addresses(get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); check(iterator != addresses.end(), "Record does not exist"); } ...
    最後,調用erase方法,刪除叠代器。壹旦該行被刪除,存儲空間就會為最初的支付者釋放。
    ... void erase(name user) { require_auth(user); address_index addresses(get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); check(iterator != addresses.end(), "Record does not exist"); addresses.erase(iterator); } ...
    現在合約差不多完成了。用戶可以創建,修改和刪除記錄。然而,合約還沒準備好被編譯。
    Step 9: 為ABI做準備
    9.1 ABI Action聲明
    eosio.cdt包含了壹個ABI生成器,但是它需要壹些聲明才能運行。
    在upsert和erase函數前添加C++11聲明。
    [[eosio::action]]
    上面這條什麽將會把action的參數提取出來,並在生成的ABI文件中創建必需的ABI結構描述。
    9.2 ABI表聲明
    把壹條ABI聲明添加到表中。把下面這條在合約私有域中定義的內容修改了:
    struct person {
    修改成下面這樣:
    struct [[eosio::table]] person {
    [[eosio.table]] 聲明會把必須的描述添加到ABI文件裏。
    現在我們的合約就可以編譯了。
    下面是我們addressbook 合約的最終的樣子:
    #include <eosio/eosio.hpp> using namespace eosio; class [[eosio::contract(“addressbook”)]] addressbook : public eosio::contract { public: addressbook(name receiver, name code, datastream<const char*> ds): contract(receiver, code, ds) {} [[eosio::action]] void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) { require_auth( user ); address_index addresses( get_self(), get_first_receiver().value ); auto iterator = addresses.find(user.value); if( iterator == addresses.end() ) { addresses.emplace(user, [&]( auto& row ) { row.key = user; row.first_name = first_name; row.last_name = last_name; row.street = street; row.city = city; row.state = state; }); } else { addresses.modify(iterator, user, [&]( auto& row ) { row.key = user; row.first_name = first_name; row.last_name = last_name; row.street = street; row.city = city; row.state = state; }); } } [[eosio::action]] void erase(name user) { require_auth(user); address_index addresses( get_self(), get_first_receiver().value); auto iterator = addresses.find(user.value); check(iterator != addresses.end(), “Record does not exist”); addresses.erase(iterator); } private: struct [[eosio::table]] person { name key; std::string first_name; std::string last_name; std::string street; std::string city; std::string state; uint64_t primary_key() const { return key.value; } }; typedef eosio::multi_index<”people”_n, person> address_index; };

Coin Marketplace

STEEM 0.30
TRX 0.12
JST 0.033
BTC 64386.10
ETH 3142.17
USDT 1.00
SBD 3.98