从数据存储中检索密钥(更新和删除实体)

时间:2018-05-14 12:31:33

标签: c# google-app-engine asp.net-core google-cloud-datastore razor-pages

我一直在阅读有关密钥的数据存储文档。

在文档中说

  

"密钥存储为对象而不是值。"

这是结果 enter image description here

以下是我的样本。 ID是我尝试检索以更新和删除实体的密钥

Sample Data

显示结果

@page
@using TestApp.Models
@model AllSportsStoreModel

<h2>Index</h2>

<p>
    <a asp-page="SportsStore">New Item</a>
</p>
    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayName("ID")
                </th>
                <th>
                    @Html.DisplayName("Name")
                </th>
                <th>
                    @Html.DisplayName("Price")
                </th>
                <th>Edit | Delete</th>
            </tr>
        </thead>
        <tbody>
@for (var i = 0; i < Model.SportsStoreList.Count; i++) {
    <tr>
        <td>
            @Html.DisplayFor(model => model.SportsStoreList[i].Id)
        </td>
        <td>
            @Html.DisplayFor(model => model.SportsStoreList[i].PName)
        </td>
        <td>
            @Html.DisplayFor(model => model.SportsStoreList[i].Price)
        </td>
        <td>
            <a asp-page="EditStore" asp-route-Id="SportsStoreList[i].Id">Edit</a> |
            <a asp-page-handler="Delete" asp-route-Id="SportsStoreList[i].Id">Delete</a>
        </td>
    </tr>
}
        </tbody>
    </table>
    <br />

代码背后:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Google.Cloud.Datastore.V1;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using TestApp.Models;

namespace TestApp.Pages
{
    public class AllSportsStoreModel : PageModel
    {
        private readonly ISportsStore stores;

        public AllSportsStoreModel(ISportsStore stores)
        {
            this.stores = stores;
        }

        [BindProperty]
        public List<Item> SportsStoreList { get; set; }

        public IActionResult OnGet()
        {
            SportsStoreList = stores.ReadAll();
            return Page();
        }

    }
}

DataStoreSportsStore.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Google.Cloud.Datastore.V1;


namespace TestApp.Models
{
    public static class DatastoreBookStoreExtensionMethods
    {
        public static Key ToKey(this long id) => new Key().WithElement("Sports_db", id);

        /// <summary>
        /// Make a id given a datastore key.
        /// </summary>
        /// <param name="key">A datastore key</param>
        /// <returns>A item id.</returns>
        public static long ToId(this Key key) => key.Path.First().Id;

        /// <summary>
        /// Create a datastore entity with the same values as item.
        /// </summary>
        /// <param name="item">The item to store in datastore.</param>
        /// <returns>A datastore entity.</returns>
        public static Entity ToEntity(this Item item) => new Entity()
        {
            Key = item.Id.ToKey(),
            ["PName"] = item.PName,
            ["Price"] = item.Price,
        };

        /// <summary>
        /// Unpack an itemfrom a datastore entity.
        /// </summary>
        /// <param name="entity">An entity retrieved from datastore.</param>
        /// <returns>An Item.</returns>
        public static Item ToItem(this Entity entity) => new Item()
        {
            Id = entity.Key.Path.First().Id,
            PName = (string)entity["PName"],
            Price = (string)entity["Price"]
        };
    }


    public class DatastoreSportsStore : ISportsStore
    {
        string kind = "Sports_db";
        private readonly DatastoreDb _db;

        public DatastoreSportsStore()
        {
            _db = DatastoreDb.Create("projectid");
        }

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

        public Item Read(long id)
        {
            return _db.Lookup(id.ToKey())?.ToItem();
        }

        public List<Item> ReadAll()
        {
            var query = new Query(kind);
            var results = _db.RunQuery(query);
            return results.Entities.Select(entity => entity.ToItem()).ToList();
        }

        public void Update(Item item)
        {
            _db.Update(item.ToEntity());
        }

        public void Delete(long id)
        {
            _db.Delete(id.ToKey());
        }

    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<ISportsStore, DatastoreSportsStore>();
    services.AddMvc();
}

Item.cs

namespace TestApp.Models
{
    public class Item
    {
        public long Id { get; set; }
        public string PName { get; set; }
        public string Price { get; set; }
    }
}

如何从数据存储区实体检索密钥以使用C#更新和删除记录?

2 个答案:

答案 0 :(得分:4)

  

如何使用C#从数据存储区实体检索密钥?

通过在文档

中提及调用Entity.Key属性
Key key = entity.Key;
  

使用实体

     

应用程序可以使用Cloud Datastore API来创建,检索,更新和删除实体。如果应用程序知道实体的完整密钥(或者可以从其父密钥,种类和标识符派生它),它可以使用密钥直接在实体上运行。

     

更新实体

     

要更新现有实体,请修改先前检索的实体的属性,并使用密钥存储它:

_item["Name"] = "John";
_item["Price"] = 12.95;
_db.Update(_item);
  

删除实体

     

给定实体的密钥,您可以删除实体:

_db.Delete(_item.Key);

上述假设是_itemEntity类型的变量。

参考Cloud Datastore Documentation: Entities, Properties, and Keys

按照这里非常有用的教程

Using Cloud Datastore with .NET

您可以尝试以下操作。

假设你有一个这样的模型(取自你以前的一个问题)

public class Item {
    public string Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

请注意Id

有一些helper methods on GitHub.的链接可以根据您的情况进行调整。

/// <summary>
/// Make a datastore key given a item's id.
/// </summary>
/// <param name="id">An Item's id.</param>
/// <returns>A datastore key.</returns>
public static Key ToKey(this string id) =>
    new Key().WithElement("Sports_db", id);

/// <summary>
/// Make a id given a datastore key.
/// </summary>
/// <param name="key">A datastore key</param>
/// <returns>A item id.</returns>
public static string ToId(this Key key) => key.Path.First().Name;

/// <summary>
/// Create a datastore entity with the same values as item.
/// </summary>
/// <param name="item">The item to store in datastore.</param>
/// <returns>A datastore entity.</returns>
public static Entity ToEntity(this Item item) => new Entity() {
    Key = item.Id.ToKey(),
    ["Name"] = item.Name,
    ["Price"] = item.Price,
};

/// <summary>
/// Unpack an itemfrom a datastore entity.
/// </summary>
/// <param name="entity">An entity retrieved from datastore.</param>
/// <returns>An Item.</returns>
public static Item ToItem(this Entity entity) => new Item() {
    Id = entity.Key.ToId(),
    Name = (string)entity["Name"],
    Price = (decimal)entity["Price"]
};

这将允许您使用扩展方法执行以下操作

SportsStoreList = stores.Select(entity => entity.ToItem()).ToList();

这再次来自上一个问题。

现在,您有一个与您合作的ID /密钥,现在应该可以根据ID /密钥进行更新

编辑项目时,您可以

var entity = item.ToEntity()
_db.Update(entity);

对于删除,您只需将ID转换回密钥

即可
var key = item.Id.ToKey();
_db.Delete(key);

更进一步,您可以将数据存储区封装在提供CRUD功能的抽象背后,并将所有与数据存储区相关的功能保存在一个中心区域

public class DatastoreSportsStore : ISportsStore {
    string kind = "Sports_db";
    private readonly DatastoreDb _db;

    public DatastoreSportsStore() {
        _db = DatastoreDb.Create("projectid");
    }

    public void Create(Item item) {
        var entity = item.ToEntity();
        entity.Key = _db.CreateKeyFactory(kind).CreateIncompleteKey();
        var keys = _db.Insert(new[] { entity });
        item.Id = keys.First().ToId();
    }

    public Item Read(string id) {
        return _db.Lookup(id.ToKey())?.ToItem();
    }

    public List<Item> ReadAll() {
        var query = new Query(kind);
        var results = _db.RunQuery(query);
        return results.Entities.Select(entity => entity.ToItem()).ToList();
    }

    public void Update(Item item) {
        _db.Update(item.ToEntity());
    }

    public void Delete(string id) {
        _db.Delete(id.ToKey());
    }
}

这样就无需在页面模型中与数据存储区进行交互。

您将在启动期间使用服务集合注册抽象

参考Introduction to Razor Pages in ASP.NET Core

Startup.cs:

public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        //...

        services.AddScoped<ISportsStore, DatastoreSportsStore>();

        //...

        // Includes support for Razor Pages and controllers.
        services.AddMvc();
    }

    //...
}

然后将其作为所需的依赖项注入。

例如,

AllSportsStore.cshtml.cs

public class AllSportsStoreModel : PageModel {

    private readonly ISportsStore stores;

    public AllSportsStoreModel(ISportsStore stores) {
        this.stores = stores;
    }

    [BindProperty]
    public List<Item> SportsStoreList { get; set; }

    public IActionResult OnGet() {
        SportsStoreList = stores.ReadAll();
        return Page();
    }
}

在上面的PageMode中,抽象商店被注入并用于获取要在视图中显示的项目

然后,您应该能够访问视图/页面中列表中的项目。

AllSportsStore.cshtml

@page
@using TestApp.Models
@model AllSportsStoreModel

<h2>Index</h2>

<p>
    <a asp-page="SportsStore">New Item</a>
</p>
    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayName("ID")
                </th>
                <th>
                    @Html.DisplayName("Name")
                </th>
                <th>
                    @Html.DisplayName("Price")
                </th>
                <th>Edit | Delete</th>
            </tr>
        </thead>
        <tbody>
@for (var i = 0; i < Model.SportsStoreList.Count; i++) {
    <tr>
        <td>
            @Html.DisplayFor(model => model.SportsStoreList[i].Id)
        </td>
        <td>
            @Html.DisplayFor(model => model.SportsStoreList[i].Name)
        </td>
        <td>
            @Html.DisplayFor(model => model.SportsStoreList[i].Price)
        </td>
        <td>
            <a asp-page="EditStore" asp-route-Id="@(Model.SportsStoreList[i].Id)">Edit</a> |
            <a asp-page-handler="Delete" asp-route-Id="@(Model.SportsStoreList[i].Id)">Delete</a>
        </td>
    </tr>
}
    </tbody>
</table>
<br />

答案 1 :(得分:2)

如果'_'是您实体的变量名称,那么要获取该实体的密钥,您将在该实体上调用Entity.Key属性。

即:

Id = _.Key,

不需要像提供的示例中的其他成员一样将其强制转换。