c# - 从数据存储中检索 key (更新和删除实体)

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

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

文档中说

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

这是结果 enter image description here

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

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());
        }

    }
}

启动.cs

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

项目.cs

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

如何使用 C# 从数据存储实体检索 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);

上面的假设是 _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/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();
    }

    //...
}

然后在需要的地方将其作为依赖项注入(inject)。

例如,

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 中注入(inject)了抽象的 store 并用于获取要在 View 中显示的项目

然后您应该能够在 View /页面中访问列表中的项目。

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

关于c# - 从数据存储中检索 key (更新和删除实体),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50330404/

相关文章:

c# - .ToDictionary C# 中的 foreach 和索引

jquery - 通过 JQuery 向 Google App Engine 发送 POST 请求时没有结果

asp.net-core - 有时 SignalR "Error during WebSocket handshake"

.NET Core 依赖注入(inject) -> 获取接口(interface)的所有实现

asp.net-core - Microsoft.Extensions.DependencyInjection 中的属性注入(inject)

c# - 在 C# 中检查集合内部的类型

c# - 引用值参数VS返回值哪个好?

c# - Web API 操作返回类型最佳实践

java - 如何使用 Java 从 Google Cloud Storage 服务器端的视频创建缩略图或 jpeg 图像

python - App Engine 上 Python 的最佳 Twitter 框架?