using Microsoft.Azure.Cosmos.Table;
using Microsoft.Azure.Cosmos.Table.Queryable;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
using System.Reflection;
namespace TEAMModelOS.SDK.DI
{
public static class AzureStorageTableExtensions
{
#region CloudTable 批次操作
///
/// 批次新增資料至Table儲存區。
///
/// 欲快取的集合
///
public static async Task BatchInsertAsync(this CloudTable table, IEnumerable entities) where T : ITableEntity, new()
{
TableBatchOperation batchOperation = new TableBatchOperation();
foreach (var cache in entities)
{
batchOperation.Insert(cache);
}
return await table.ExecuteBatchAsync(batchOperation);
}
#endregion
#region CloudTable Get
///
/// (同步)取得 table 中指定 PartitionKey 的所有集合。
///
///
public static IEnumerable Get(this CloudTable table, string partitionKey) where T : ITableEntity, new()
{
TableQuery query = new TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey));
return table.ExecuteQuery(query);
}
///
/// (同步)取得指定 PartitionKey與 RowKey 的數據,效能:點查詢,最佳。
///
/// T
/// PartitionKey
/// RowKey
///
public static T Get(this CloudTable table, string partitionKey, string rowKey) where T : ITableEntity, new()
{
TableOperation retrieveOperation = TableOperation.Retrieve(partitionKey, rowKey);
var retrieveResult = table.Execute(retrieveOperation);
if (retrieveResult.Result != null)
{
//DynamicTableEntityJsonSeria1lizer
return (T)retrieveResult.Result;
}
else
{
return default(T);
}
}
public static DynamicTableEntity Get(this CloudTable table, string partitionKey, string rowKey)
{
TableOperation retrieveOperation = TableOperation.Retrieve(partitionKey, rowKey);
var retrieveResult = table.Execute(retrieveOperation);
if (retrieveResult.Result != null)
{
return retrieveResult.Result as DynamicTableEntity;
}
else
{
return null;
}
}
///
/// 取得指定 PartitionKey 的所有集合(分頁),效能:範圍查詢,次佳。
///
/// T
/// PartitionKey
/// 指定每次返回數量
/// 指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本
/// 要返回集合的委派
/// CancellationToken
///
public static async Task GetAsync(this CloudTable table, string partitionKey, int? takeCount = null, List specifyPropertys = null, Action> onProgress = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
{
TableQuery tableQuery = null;
TableContinuationToken token = null;
var filter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey);
if (specifyPropertys != null)
tableQuery = new TableQuery().Where(filter).Select(specifyPropertys);
else
tableQuery = new TableQuery().Where(filter);
if (takeCount != null) tableQuery.TakeCount = takeCount;
do
{
var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
token = queryResponse.ContinuationToken;
onProgress?.Invoke(queryResponse.Results);
} while (token != null && !ct.IsCancellationRequested);
}
///
/// 取得指定 PartitionKey 的所有集合,效能:範圍查詢,次佳。
///
/// T
/// PartitionKey
/// 指定每次返回數量
/// 指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本
/// 要返回集合的委派
/// CancellationToken
///
public static async Task> GetAsync(this CloudTable table, string partitionKey, int? takeCount = null, List specifyPropertys = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
{
TableQuery tableQuery = null;
TableContinuationToken token = null;
var filter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey);
if (specifyPropertys != null)
tableQuery = new TableQuery().Where(filter).Select(specifyPropertys);
else
tableQuery = new TableQuery().Where(filter);
if (takeCount != null) tableQuery.TakeCount = takeCount;
var items = new List();
do
{
var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
token = queryResponse.ContinuationToken;
items.AddRange(queryResponse.Results);
} while (token != null && !ct.IsCancellationRequested);
return items;
}
///
/// 傳回指定partitionKey的Count數量
///
///
///
public static int GetCount(this CloudTable table, string partitionKey)
{
TableQuery query = new TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey)).Select(new List { "PartitionKey" });
var queryResponse = table.ExecuteQuery(query).ToList();
return queryResponse.Count();
}
#endregion
#region CloudTable Get All
///
/// (同步)取得 table 的所有集合,效能:資料表掃描,不佳。
///
///
public static IEnumerable GetAll(this CloudTable table) where T : ITableEntity, new()
{
return table.ExecuteQuery(new TableQuery());
}
///
/// 取得 table 的所有集合(分頁),效能:資料表掃描,不佳。
///
/// 指定每次返回數量
/// 指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本
/// 要返回集合的委派
///
public static async Task GetAllAsync(this CloudTable table, int? takeCount = null, List specifyPropertys = null, Action> onProgress = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
{
TableContinuationToken token = null;
TableQuery tableQuery = new TableQuery();
if (specifyPropertys != null)
tableQuery = new TableQuery().Select(specifyPropertys);
else
tableQuery = new TableQuery();
if (takeCount != null) tableQuery.TakeCount = takeCount;
var items = new List();
do
{
var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
token = queryResponse.ContinuationToken;
items.AddRange(queryResponse.Results);
onProgress?.Invoke(queryResponse.Results);
} while (token != null && !ct.IsCancellationRequested);
}
///
/// 取得 table 的所有集合,效能:資料表掃描,不佳。
///
/// 指定每次返回數量
/// 指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本
///
public static async Task> GetAllAsync(this CloudTable table, int? takeCount = null, List specifyPropertys = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
{
TableContinuationToken token = null;
TableQuery tableQuery = new TableQuery();
if (takeCount != null) tableQuery.TakeCount = takeCount;
if (specifyPropertys != null)
tableQuery = new TableQuery().Select(specifyPropertys);
else
tableQuery = new TableQuery();
var items = new List();
do
{
var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
token = queryResponse.ContinuationToken;
items.AddRange(queryResponse.Results);
} while (token != null && !ct.IsCancellationRequested);
return items;
}
#endregion
public static async Task Save(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
{
CloudTable TableName = await azureStorageFactory.InitializeTable();
TableOperation operation = TableOperation.Insert(entity);
TableResult result = await TableName.ExecuteAsync(operation);
return (T)result.Result;
}
public static async Task SaveOrUpdate(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
{
CloudTable TableName = await azureStorageFactory.InitializeTable();
TableOperation operation = TableOperation.InsertOrReplace(entity);
TableResult result = await TableName.ExecuteAsync(operation);
return (T)result.Result;
}
public static async Task Update(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
{
CloudTable TableName = await azureStorageFactory.InitializeTable();
TableOperation operation = TableOperation.Replace(entity);
TableResult result = await TableName.ExecuteAsync(operation);
return (T)result.Result;
}
public static async Task Delete(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
{
CloudTable TableName = await azureStorageFactory.InitializeTable();
TableOperation operation = TableOperation.Delete(entity);
TableResult result = await TableName.ExecuteAsync(operation);
return (T)result.Result;
}
public static async Task> DeleteAll(this AzureStorageFactory azureStorageFactory, List entitys) where T : TableEntity, new()
{
if (entitys.IsEmpty())
{
return null;
}
CloudTable TableName = await azureStorageFactory.InitializeTable();
IList>> listInfo = new List>>();
foreach (IGrouping group in entitys.GroupBy(c => c.PartitionKey))
{
Dictionary> dictInfo = new Dictionary>
{
{ group.Key, group.ToList() }
};
listInfo.Add(dictInfo);
}
foreach (Dictionary> dict in listInfo)
{
IList result = null;
foreach (string key in dict.Keys)
{
List values = dict[key];
int pageSize = 100;
int pages = (int)Math.Ceiling((double)values.Count / pageSize);
for (int i = 0; i < pages; i++)
{
List lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
TableBatchOperation batchOperation = new TableBatchOperation();
for (int j = 0; j < lists.Count; j++)
{
batchOperation.Delete(lists[j]);
}
result = await TableName.ExecuteBatchAsync(batchOperation);
}
}
}
return entitys;
}
public static async Task> SaveOrUpdateAll(this AzureStorageFactory azureStorageFactory, List entitys) where T : TableEntity, new()
{
if (entitys.IsEmpty())
{
return null;
}
CloudTable TableName = await azureStorageFactory.InitializeTable();
IList>> listInfo = new List>>();
foreach (IGrouping group in entitys.GroupBy(c => c.PartitionKey))
{
Dictionary> dictInfo = new Dictionary>
{
{ group.Key, group.ToList() }
};
listInfo.Add(dictInfo);
}
foreach (Dictionary> dict in listInfo)
{
IList result = null;
foreach (string key in dict.Keys)
{
List values = dict[key];
int pageSize = 100;
int pages = (int)Math.Ceiling((double)values.Count / pageSize);
for (int i = 0; i < pages; i++)
{
List lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
TableBatchOperation batchOperation = new TableBatchOperation();
for (int j = 0; j < lists.Count; j++)
{
batchOperation.InsertOrReplace(lists[j]);
}
result = await TableName.ExecuteBatchAsync(batchOperation);
}
}
}
return entitys;
}
public static async Task> UpdateAll(this AzureStorageFactory azureStorageFactory, List entitys) where T : TableEntity, new()
{
if (entitys.IsEmpty())
{
return null;
}
CloudTable TableName = await azureStorageFactory.InitializeTable();
IList>> listInfo = new List>>();
foreach (IGrouping group in entitys.GroupBy(c => c.PartitionKey))
{
Dictionary> dictInfo = new Dictionary>
{
{ group.Key, group.ToList() }
};
listInfo.Add(dictInfo);
}
foreach (Dictionary> dict in listInfo)
{
IList result = null;
foreach (string key in dict.Keys)
{
List values = dict[key];
int pageSize = 100;
int pages = (int)Math.Ceiling((double)values.Count / pageSize);
for (int i = 0; i < pages; i++)
{
List lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
TableBatchOperation batchOperation = new TableBatchOperation();
for (int j = 0; j < lists.Count; j++)
{
batchOperation.Replace(lists[j]);
}
result = await TableName.ExecuteBatchAsync(batchOperation);
}
}
}
return entitys;
}
public static async Task> SaveAll(this AzureStorageFactory azureStorageFactory, List entitys) where T : TableEntity, new()
{
if (entitys.IsEmpty())
{
return null;
}
CloudTable TableName = await azureStorageFactory.InitializeTable();
IList>> listInfo = new List>>();
foreach (IGrouping group in entitys.GroupBy(c => c.PartitionKey))
{
Dictionary> dictInfo = new Dictionary>
{
{ group.Key, group.ToList() }
};
listInfo.Add(dictInfo);
}
foreach (Dictionary> dict in listInfo)
{
IList result = null;
foreach (string key in dict.Keys)
{
List values = dict[key];
int pageSize = 100;
int pages = (int)Math.Ceiling((double)values.Count / pageSize);
for (int i = 0; i < pages; i++)
{
List lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
TableBatchOperation batchOperation = new TableBatchOperation();
for (int j = 0; j < lists.Count; j++)
{
batchOperation.Insert(lists[j]);
}
result = await TableName.ExecuteBatchAsync(batchOperation);
}
}
}
return entitys;
}
public static async Task> FindListByDict(this AzureStorageFactory azureStorageFactory, Dictionary dict) where T : TableEntity, new()
{
CloudTable TableName = await azureStorageFactory.InitializeTable();
var exQuery = new TableQuery();
StringBuilder builder = new StringBuilder();
if (null != dict && dict.Count > 0)
{
var keys = dict.Keys;
int index = 1;
foreach (string key in keys)
{
if (dict[key] != null && !string.IsNullOrEmpty(dict[key].ToString()))
{
string typeStr = SwitchType(dict[key], key);
if (string.IsNullOrEmpty(typeStr))
{
continue;
}
if (index == 1)
{
//builder.Append(TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, dict[key].ToString()));
builder.Append(typeStr);
}
else
{
//builder.Append(" " + TableOperators.And + " " + TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, dict[key].ToString()));
builder.Append(" " + TableOperators.And + " " + typeStr);
}
index++;
}
else
{
throw new Exception("The parameter must have value!");
}
}
exQuery.Where(builder.ToString());
return await QueryList(exQuery, TableName);
}
else
{
return null;
}
}
private static async Task> QueryList(TableQuery exQuery, CloudTable TableName ) where T : TableEntity, new()
{
TableContinuationToken continuationToken = null;
List entitys = new List();
do
{
var result = await TableName.ExecuteQuerySegmentedAsync(exQuery, continuationToken);
if (result.Results.Count > 0)
{
entitys.AddRange(result.ToList());
}
continuationToken = result.ContinuationToken;
} while (continuationToken != null);
return entitys;
}
private static string SwitchType(object obj, string key)
{
Type objType = typeof(T);
PropertyInfo property = objType.GetProperty(key);
//Type s = obj.GetType();
//TypeCode typeCode = Type.GetTypeCode(s);
if (property == null)
{
//return null;
throw new Exception(objType.FullName + " PropertyInfo doesn't include this parameter :" + key);
}
TypeCode typeCode = Type.GetTypeCode(property.PropertyType);
switch (typeCode)
{
case TypeCode.String: return TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, obj.ToString());
case TypeCode.Int32: return TableQuery.GenerateFilterConditionForInt(key, QueryComparisons.Equal, int.Parse(obj.ToString()));
case TypeCode.Double: return TableQuery.GenerateFilterConditionForDouble(key, QueryComparisons.Equal, (double)obj);
case TypeCode.Byte: return TableQuery.GenerateFilterConditionForBinary(key, QueryComparisons.Equal, (byte[])obj);
case TypeCode.Boolean: return TableQuery.GenerateFilterConditionForBool(key, QueryComparisons.Equal, (bool)obj);
case TypeCode.DateTime: return TableQuery.GenerateFilterConditionForDate(key, QueryComparisons.Equal, (DateTimeOffset)obj);
case TypeCode.Int64: return TableQuery.GenerateFilterConditionForLong(key, QueryComparisons.Equal, long.Parse(obj.ToString()));
default: return null;
}
}
}
}