.NET中的Azure表存储查询,其属性名称在设计时未知

时间:2012-01-10 15:28:44

标签: linq azure azure-table-storage

Azure表存储是否存在TSQL等效项? 我想在设计时不知道属性名称时在.NET中添加hock类型查询。

从我对LINQ的不足看,您需要引用现有的公共属性。

 var selectedOrders = from o in context.Orders
                 where o.Freight > 30
                 orderby o.ShippedDate descending 
                 select o;

Freight和ShippedDate必须是在设计时定义的公共属性。我没有结构化属性(甚至是结构化类)。

如果我在设计时不知道属性名称怎么办?您可以以非常多的方式向表中添加新的属性名称,但是如何使用它们呢?

通过REST API可以定义动态查询

    Request Syntax:
    GET /myaccount/Customers()?$filter=(Rating%20ge%203)%20and%20(Rating%20le%206)$select=PartitionKey,RowKey,Address,CustomerSince  HTTP/1.1

是否有工具在.NET中使用REST(以动态方式)?

来自REST API文档: 使用.NET客户端库为ADO.NET数据服务框架定义的逻辑运算符将属性与值进行比较。请注意,无法将属性与动态值进行比较;表达式的一侧必须是常量。 http://msdn.microsoft.com/en-us/library/windowsazure/dd894031.aspx

如果您需要TSQL类型查询,则需要使用SQL,然后确定。

我认为我正在学习的是Table Storage旨在序列化类(特别是如果你有许多实例要序列化)。从这个链接: http://msdn.microsoft.com/en-us/library/windowsazure/dd179423.aspx 表的模式定义为C#类。这是ADO.NET Data Services使用的模型。该架构仅为客户端应用程序所知,并简化了数据访问。服务器不强制执行此架构。

    [DataServiceKey("PartitionKey", "RowKey")]
    public class Blog
    {
        // ChannelName 
        public string PartitionKey { get; set; } 
        // PostedDate 
        public string RowKey { get; set; } 

        // User defined properties
        public string Text { get; set; }
        public int Rating { get; set; }
        public string RatingAsString { get; }
        protected string Id { get; set; }
    } 

用户将上传一个将转到BLOB的文件和用于描述该文件的字符串字段。它需要能够扩展到数百万条记录。只搜索两个必填字段(属性):custID和batch。不需要搜索其他字段,但我需要保留它们并允许用户只是批量添加新字段。需要它扩展到数百万条记录,因此BLOB存储适用于文件。我认为我从Table Storage中获得的是能够在客户端使用REST来下载文件和字段。需要一次优化多达100,000个下载并支持重新启动。上传将是相对较小的批次,这可能不是REST,因为我需要在服务器端进行一些上传验证。

我正在考虑做的是两张桌子。其中第二个是为动态数据而设计的。

    Master
      PartitionKey CustID 
      RowKey       GUID
      string       batch
      string       filename
    Fields
      PartitionKey CustID+Guid
      RowKey       fieldName
      string       value

fieldName必须是唯一的。 Master上的查询将由CustID或CustID和批处理。 对Fields的查询将由PartitionKey完成。 请评论。

6 个答案:

答案 0 :(得分:3)

我还创建了一个库,用于将动态类型与表存储一起使用:

要使用它,首先要创建一个上下文对象:

var context = new DynamicTableContext("TableName", credentials); 

然后插入记录很简单:

context.Insert(new { PartitionKey="1", RowKey="1", Value1="Hello", Value2="World" }); 

你可以用字典做同样的事情:

var dictionary = new Dictionary<string, object>();
dictionary["PartitionKey"] = "2";
dictionary["RowKey"] = "2";
dictionary["Value3"] = "FooBar";
context.Insert(dictionary); 

检索实体是直截了当的,只需传入分区键和行键的值:

dynamic entity = content.Get("1", "1"); 

您还可以传递查询:

foreach (dynamic item in context.Query("Value1 eq 'Hello'"))
{
  Console.WriteLine(item.RowKey);
}

它可以在github上找到:https://github.com/richorama/AzureSugar

答案 1 :(得分:1)

这不是表存储的问题,而是LINQ。您可以使用表达式树编写动态LINQ(遗憾的是失去了为什么LINQ非常棒)。无论如何,LINQ实际上只是背景中的表达式树。

对你的问题有三个回答:

  1. 以下是编写dynamic LINQ

  2. 的方法
  3. 以下是关于dynamic LINQ library以减少丑陋的信息

  4. 最后你不能在表存储查询中使用order by:)

答案 2 :(得分:1)

我正在为REST API创建一个动态客户端 它被称为Cyan,您可以在Codeplex或nuget中搜索“Cyan”。

您的查询将是:

var cyan = new CyanTableClient("account", "password")
var items = cyan.Query("Customers",
    filter: "(Rating ge 3) and (Rating le 6)",
    fields: new[] { "PartitionKey", "RowKey", "Address", "CustomerSince" });

然后您可以通过以下方式访问字段:

var item = items.First();

// the address
string address = item.Address;

// or you can cast to CyanEntity and access fields from a Dictionary
var entity = (CyanEntity)item;
string address2 = (string)entity.Fields["Address"];

这仍然是一项正在进行中的工作,请将您的反馈意见发送给我,并随时做出贡献!

答案 3 :(得分:1)

我编写了一个Azure表存储客户端,它支持静态和后期绑定(通过字典)。任何未包含在实体类型中的表属性都将在字典中捕获。它还支持数组,枚举,大数据,序列化等。更多功能也在开发中!

你可以在http://www.lucifure.com获得它。

答案 4 :(得分:0)

我有一个类似的问题,最初通过像你的“字段”表这样的表来接近它 - 许多非常小的记录带有键/值。我遇到了两个问题 - 一个是Nagle's algorithm messes with your inserts,如果你不是异步(每个插入最多500毫秒),另一个是Azure's scalability targets限制你在存储帐户中的20,000个实体/秒

最后,我通过使用自定义读/写方法存储Dictionary<string, string>来解决它,我在How can I store arbitrary key value pairs in Azure table storage?

中写了这个

答案 5 :(得分:0)

Azure表服务不支持按查询排序,它仅支持whereselectfirstfirstorsdefaultfrom和{{1} }。你可以写两个单独的查询。