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

Retrieve Key from Datastore (Update & Delete Entity)

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

文档中说

"a key is stored as an object not as a value."

这是结果

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

显示结果

@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# 从数据存储实体检索密钥以更新和删除记录?

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

即:

Id = _.Key,

不需要像提供的示例中的其他成员那样进行转换..

How does one retrieve a key from the Datastore Entity using C#?

通过调用文档中提到的 Entity.Key 属性

Key key = entity.Key;

Working with entities

Applications can use the Cloud Datastore API to create, retrieve, update, and delete entities. If the application knows the complete key for an entity (or can derive it from its parent key, kind, and identifier), it can use the key to operate directly on the entity.

Updating an entity

To update an existing entity, modify the properties of the entity previously retrieved and store it using the key:

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

Deleting an entity

Given an entity's key, you can delete the entity:

_db.Delete(_item.Key);

上面的假设是_item是一个Entity类型的变量。

参考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

有些人 link 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/Key 可以使用,您现在应该能够根据 Id/Key

执行更新

编辑项目时,您可以

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

对于删除,您只需将 Id 转换回 Key

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抽象存储被注入并用于获取要在视图中显示的项目

然后您应该能够访问 view/page 中列表中的项目。

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 />