处理 类 继承 Table 实体的 Azure Table 存储的批处理器

Batch processor for Azure Table Storage that handles classes inheriting TableEntity

我有许多不同的 Azure Table我想写信给它们,它们具有一些核心属性和一些不同的属性。我想分批编写以最大限度地降低成本,但我正在努力让处理器函数中的类型正确以促进这一点。

应该使用什么类型或附加代码来使这个函数处理范例类?

批处理代码和重现

using System;
using System.Collections.Generic;
using Microsoft.WindowsAzure.Storage.Table;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
    }

    static void BatchInsertOrReplace<ITableEntity>(List<ITableEntity> items, CloudTable table)
    {
        // setup
        List<ITableEntity> batch = new List<T>();
        TableBatchOperation batchOperation = new TableBatchOperation();
        // n-1 batches
        foreach (var item in items)
        {
            batch.Add(item);
            batchOperation.InsertOrReplace(item);
            if (batch.Count == 100)
            {
                table.ExecuteBatch(batchOperation);
                batchOperation.Clear();
                batch.Clear();
            }
        }

        // nth batch
        if (batch.Any())
        {
            table.ExecuteBatch(batchOperation);
        }
    }

    // things I want to be able to push to table storage
    public class exampleClass : TableEntity
    {
        public DateTime rawDate { get; set; }
    }

    public class exampleClass_deriv1 : exampleClass
    {
        public string User { get; set; }
        public string Device { get; set; }
    }

    public class exampleClass_deriv2 : exampleClass
    {
        public string Person { get; set; }
        public string Machine { get; set; }
    }
}

示例用法

我从 Azure Table 存储中检索实体并当前转换它们的代码:

IEnumerable<exampleClass> recs = (from r in mytable
                                   where r.rawDate >= DateTime.Now
                                   select r);
var recsaccount = recs
    .Select(r => new exampleClass_deriv1
    {
        PartitionKey = r.PartitionKey,
        RowKey = r.RowKey,
        rawDate = r.rawDate,
        epochDate = i.epochDate,
        User = "Jim",
        Device = "Palmpilot"
    });
// Desired execution (which errors)
BatchInsertOrReplace(recsaccount.ToList(), mytable);

(List<ITableEntity>)recsaccount.ToList()这样的简单强制转换不起作用

run.csx(63,30): error CS0030: Cannot convert type 'System.Collections.Generic.List<exampleClass_deriv2>' to 'System.Collections.Generic.List<ITableEntity>'

更新 1

创建一个新列表并首先将项目放入其中:

List<ITableEntity> ins = new List<ITableEntity>();
foreach (var blah in recs.ToList())
{
   ITableEntity newOne = (ITableEntity)blah;
    ins.Add(newOne);
}
BatchInsertOrReplace(ins, mytable);

导致如下错误:

error CS0411: The type arguments for method 'BatchInsertOrReplace<T>(List<ITableEntity>, CloudTable)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

尝试使用类型前缀并没有改变这种情况。

更新 2 - 使用 <T>

如果我在函数定义中使用 <T>

static void BatchInsertOrReplace<T>(List<T> items, CloudTable table)
{
    List<T> batch = new List<T>(); // Alt of List<ITableEntity> batch = new List<ITableEntity>(); 
    TableBatchOperation batchOperation = new TableBatchOperation();
    foreach (var item in items)
    {
        batch.Add(item);
        batchOperation.InsertOrReplace(item);

        if (batch.Count == 100)
        {
            table.ExecuteBatch(batchOperation);
            batchOperation.Clear();
            batch.Clear();
        }
    }

    // Process last batch
    if (batch.Any())
    {
        table.ExecuteBatch(batchOperation);
    }
}

然后使用像这样的函数 BatchInsertOrReplace<exampleClass_deriv2>( recsaccount.ToList(), webhitsAggAccount); 导致有关 batch.AddbatchOperation.InsertOrReplace

的消息
run.csx(128,19): error CS1503: Argument 1: cannot convert from 'T' to 'Microsoft.WindowsAzure.Storage.Table.ITableEntity'
run.csx(129,40): error CS1503: Argument 1: cannot convert from 'T' to 'Microsoft.WindowsAzure.Storage.Table.ITableEntity'

无论 batch 是构造为 List<ITableEntity> 还是 List<T>,都会发生这种情况。

您应该确保函数定义允许变量类型,方法是使其签名使用 T,但声明 T 继承 ITableEntity。这可以通过将 where 子句作为函数第一个声明的一部分来完成。您的批处理函数将变为:

static void BatchInsertOrReplace<T>(List<T> items, CloudTable table) where T : ITableEntity
{
    List<ITableEntity> batch = new List<ITableEntity>();
    TableBatchOperation batchOperation = new TableBatchOperation();
    foreach (var item in items)
    {
        batch.Add(item);
        batchOperation.InsertOrReplace(item);

        if (batch.Count == 100)
        {
            table.ExecuteBatch(batchOperation);
            batchOperation.Clear();
            batch.Clear();
        }
    }

    // Process last batch
    if (batch.Any())
    {
        table.ExecuteBatch(batchOperation);
    }
}