从数据存储中检索密钥(更新和删除实体)
Posted
技术标签:
【中文标题】从数据存储中检索密钥(更新和删除实体)【英文标题】:Retrieve Key from Datastore (Update & Delete Entity) 【发布时间】:2018-10-24 02:51:08 【问题描述】:我一直在阅读有关密钥的 Datastore 文档。
在文档中它说
“一个键被存储为一个对象而不是一个值。”
这是结果
下面是我的一个样本。 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# 从数据存储实体中检索密钥以更新和删除记录?
【问题讨论】:
@Nkosi 类型是 Key 您是否阅读过这些文档,它们向您展示了这一点? cloud.google.com/datastore/docs/concepts/… 有一个 c# 选项卡显示它。 @DanNick 酷。请务必查看包含的链接。他们非常有帮助。海事组织 @Nkosi 我更好地理解了这个例子。但是如何显示数据?我试过这个:foreach (var item in Model.ReadAll()) 它返回一个空豁免错误。 快速提问。您更喜欢在项目模型中使用long
还是字符串 id?还是对你没关系?
【参考方案1】:
如何使用 C# 从数据存储实体中检索密钥?
通过调用文档中提到的 Entity.Key
属性
Key key = entity.Key;
使用实体
应用程序可以使用 Cloud Datastore API 来创建、检索、更新和删除实体。如果应用程序知道实体的完整密钥(或可以从其父密钥、种类和标识符派生出来),它可以使用该密钥直接对实体进行操作。
更新实体
要更新现有实体,请修改之前检索到的实体的属性并使用密钥存储它:
_item["Name"] = "John";
_item["Price"] = 12.95;
_db.Update(_item);
删除实体
给定实体的键,你可以删除实体:
_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
有一个链接到一些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);
更进一步,您可以将 Datastore 封装在提供 CRUD 功能并将所有与 Datastore 相关的功能保持在一个中心区域的抽象后面
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
中注入了抽象的store,用来获取要在视图中显示的item
然后您应该能够访问视图/页面中列表中的项目。
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 />
【讨论】:
@DanNick 在 GitHub 的源代码中找到了PathElement
的 Name
属性中的值,但它是一个字符串。仔细检查我所做的更改。我会离开我的办公桌,离开电网一段时间。稍后入住。【参考方案2】:
如果'_'
是实体的变量名,那么要获取实体的键,您将调用实体的Entity.Key 属性。
即:
Id = _.Key,
不需要像提供的示例中的其他成员一样强制转换它..
【讨论】:
我更新了代码以显示错误消息。该建议无效。以上是关于从数据存储中检索密钥(更新和删除实体)的主要内容,如果未能解决你的问题,请参考以下文章