將 Cloud Datastore 與 .NET 搭配使用

這部分 .NET Bookshelf 教學課程說明如何在 Cloud Datastore 中建立、讀取、更新及刪除結構化資料。

本頁面是多頁教學課程的一部分。如要從頭開始,並閱讀設定的操作說明,請前往 .NET Bookshelf 應用程式

設定

  1. 如要在 Visual Studio 中開啟範例應用程式,請在 getting-started-dotnet\aspnet\2-structured-data 目錄中按兩下 2-structured-data.sln

  2. 在「方案總管」窗格中,按一下 Web.config

  3. Web.config 中,完成下列步驟:

    1. GoogleCloudSamples:ProjectId 設定為您的專案 ID。

    2. GoogleCloudSamples:BookStore 設定為 datastore

  4. 儲存並關閉 Web.config

在本機電腦執行應用程式

在 Visual Studio 中,按 F5 以執行專案。現在,您可以瀏覽應用程式的網頁,以新增、編輯與刪除書籍。

將應用程式部署至 Compute Engine

  1. 在 Visual Studio 的「Solution Explorer」(方案總管) 窗格中,以滑鼠右鍵按一下 [2-structured-data],然後點選 [Publish] (發行)

    發行應用程式

  2. 在「發行 Web」 對話方塊中,選取 [自訂] 做為發行目標。

  3. 在「New Custom Profile」(新增自訂設定檔) 對話方塊中,針對「Profile name」(設定檔名稱),輸入 bookshelf-profile。點選 [確定]

  4. 填寫個人資料:

    1. 針對「伺服器」,輸入 Compute Engine 執行個體的外部 IP 位址。

    2. 針對「Site name」(站台名稱),輸入 Default Web Site

    3. 針對「使用者名稱」,輸入您在 Compute Engine 執行個體中建立之 Windows 使用者帳戶的使用者名稱。

    4. 針對「密碼」,輸入您在 Compute Engine 執行個體中建立之 Windows 使用者帳戶的密碼。

    5. 針對「Destination URL」(目的地 URL),輸入 http://[EXTERNAL_IP_ADDRESS_OF_YOUR_COMPUTE_ENGINE_INSTANCE]

      其中:

      • [EXTERNAL_IP_ADDRESS_OF_YOUR_COMPUTE_ENGINE_INSTANCE] 表示 Compute Engine 執行個體的外部 IP 位址。
  5. 如要檢查您的個人資料憑證與設定,請按一下 [驗證連接]

  6. 由於根據預設,部署作業中的 Microsoft IIS 安裝會使用自行簽署的憑證,因此在驗證程序期間會顯示「憑證錯誤」。按一下 [儲存這個憑證以供未來 Visual Studio 工作階段使用] 的方塊,然後點選 [接受] 以接受憑證。

  7. 按一下 [設定]

  8. 按一下 [檔案發行選項],然後選取 [移除目的地的其他檔案]。將新網站發行到相同的 Compute Engine 執行個體時,此步驟對後續步驟的進行很重要。

  9. 如要部署相同的網路應用程式,請按一下 [發行]。發行完成之後,Visual Studio 會在預設網路瀏覽器中開啟應用程式。

應用程式結構

下圖顯示應用程式的元件,以及這些元件的搭配方式。該應用程式遵循傳統的 ASP.NET MVC 模式。在 BooksControllerDatastoreBookStore 之間存在一個 IBookStore 介面,因此您可以在不更動任何程式碼的情況下,將書籍資料改儲存在 Cloud SQL 中。

Bookshelf 應用程式結構

瞭解程式碼

這部分內容會逐步引導您瞭解應用程式程式碼,並說明其運作方式。

資料模型

Book 類別保留關於一本書的資訊,還有其他欄位可供後續教學課程使用。

    [Bind(Include = "Title, Author, PublishedDate, Description")]
    public class Book
    {
        [Key]
        public long Id { get; set; }

        [Required]
        public string Title { get; set; }

        public string Author { get; set; }

        [Display(Name = "Date Published")]
        [DataType(DataType.Date)]
        public DateTime? PublishedDate { get; set; }

        public string ImageUrl { get; set; }

        [DataType(DataType.MultilineText)]
        public string Description { get; set; }

        public string CreatedById { get; set; }
    }

透過表單處理使用者提交內容

您可以透過新增/編輯 HTML 表單的方式,在應用程式中新增及編輯書籍提交內容。

新增/編輯表單的圖片

HTML 表單使用 Razor 範本建立。這個 Razor 範本指定表單包含「Title」、「Author」、「Date Published」和「Description」的文字輸入欄位。

<form action="/Books/@Model.FormAction/@Model.Book.Id" method="post" id="book-form" enctype="multipart/form-data">
    @Html.AntiForgeryToken()
    <div class="form-group">
        @Html.LabelFor(model => model.Book.Title)
        @Html.EditorFor(model => model.Book.Title, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Book.Title, "", new { @class = "text-danger" })
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Book.Author)
        @Html.EditorFor(model => model.Book.Author, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Book.Author, "", new { @class = "text-danger" })
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Book.PublishedDate)
        @Html.EditorFor(model => model.Book.PublishedDate, new { htmlAttributes = new { @class = "form-control", @type = "text" } })
        @Html.ValidationMessageFor(model => model.Book.PublishedDate, "", new { @class = "text-danger" })
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Book.Description)
        @Html.EditorFor(model => model.Book.Description, new { htmlAttributes = new { @class = "form-control", @type = "text" } })
        @Html.ValidationMessageFor(model => model.Book.Description, "", new { @class = "text-danger" })
    </div>

    <button type="submit" class="btn btn-success">Save</button>
</form>

處理表單提交內容

當您按一下 [Add Book] (新增書籍) 時,BooksController.Create() 方法隨即會顯示表單。填寫表單並按一下 [Save] (儲存) 之後,BooksController.Create() 方法會收到表單的內容,並透過 IBookStore::Create() 方法將內容傳送至 Cloud SQL 資料庫。請注意,Create 方法會以 HttpPost 加註。

        // GET: Books/Create
        public ActionResult Create()
        {
            return ViewForm("Create", "Create");
        }

        // POST: Books/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Book book)
        {
            if (ModelState.IsValid)
            {
                _store.Create(book);
                return RedirectToAction("Details", new { id = book.Id });
            }
            return ViewForm("Create", "Create", book);
        }

DatastoreBookStore 類別會呼叫 Cloud Datastore API 以執行查詢並執行 CreateReadUpdateDelete (CRUD) 作業。

以下是 Create 方法:

public void Create(Book book)
{
    var entity = book.ToEntity();
    entity.Key = _db.CreateKeyFactory("Book").CreateIncompleteKey();
    var keys = _db.Insert(new[] { entity });
    book.Id = keys.First().Path.First().Id;
}

首先,Create 會呼叫 CreateIncompleteKey,進而讓 Cloud Datastore 為新實體建立金鑰。然後,該方法會呼叫 Insert 以將新書籍插入 Cloud Datastore。最後,該方法會以 Cloud Datastore 建立的新金鑰更新書籍的 ID。系統不會依序建立 ID。

DatastoreBookStoreExtensionMethods 類別使用輔助方法,更輕鬆地將 Book 封裝到 Cloud Datastore 中。ToEntity 輔助方法會將 Book 轉換為 Cloud Datastore 實體。

public static Entity ToEntity(this Book book) => new Entity()
{
    Key = book.Id.ToKey(),
    ["Title"] = book.Title,
    ["Author"] = book.Author,
    ["PublishedDate"] = book.PublishedDate?.ToUniversalTime(),
    ["ImageUrl"] = book.ImageUrl,
    ["Description"] = book.Description,
    ["CreateById"] = book.CreatedById
};

請參閱 GitHub 中的所有輔助方法

列出書籍

新增書籍之後,請按一下 [Books] (書籍) 連結前往 /Books 頁面,該頁面會列出目前儲存在 Cloud Datastore 中的所有書籍。List 方法會使用從 Cloud Datastore 擷取的資料列出所有書籍。

public BookList List(int pageSize, string nextPageToken)
{
    var query = new Query("Book") { Limit = pageSize };
    if (!string.IsNullOrWhiteSpace(nextPageToken))
        query.StartCursor = ByteString.FromBase64(nextPageToken);
    var results = _db.RunQuery(query);
    return new BookList()
    {
        Books = results.Entities.Select(entity => entity.ToBook()),
        NextPageToken = results.Entities.Count == query.Limit ?
            results.EndCursor.ToBase64() : null
    };
}

List 方法會建立並執行 Query 以尋找種類為 Book. 的所有實體。 該方法會使用 Cloud Datastore 的查詢游標實作分頁。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁