gpt4 book ai didi

azure - 您可以将 Azure 表存储 IQueryable ( table.CreateQuery() ) 公开为 POCO 吗?

转载 作者:行者123 更新时间:2023-12-02 07:30:26 25 4
gpt4 key购买 nike

我有一个包含 30 多个项目的大型应用程序,当前使用 IRepository 和 POCO 实体。我想知道是否有一种方法可以使用表存储而不必实现 ITableEntity。我不想将 Azure 存储 block 包导入到每个项目中并将所有实体更改为使用 ITableEntity。

实体适配器

我知道可以创建一个实体适配器(如下所示),它在读取或写入单个实体时效果很好。但当我尝试通过 table.CreateQuery() 公开 IQueryable 时,我无法让它工作。

public class AzureEntity
{
public Guid Id { get; set; }
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public DateTimeOffset Timestamp { get; set; }
public string ETag { get; set; }
}

internal class AzureStorageEntityAdapter<T> : ITableEntity where T : AzureEntity, new()
{
#region Properties
/// <summary>
/// Gets or sets the entity's partition key
/// </summary>
public string PartitionKey
{
get { return InnerObject.PartitionKey; }
set { InnerObject.PartitionKey = value; }
}

/// <summary>
/// Gets or sets the entity's row key.
/// </summary>
public string RowKey
{
get { return InnerObject.RowKey; }
set { InnerObject.RowKey = value; }
}

/// <summary>
/// Gets or sets the entity's Timestamp.
/// </summary>
public DateTimeOffset Timestamp
{
get { return InnerObject.Timestamp; }
set { InnerObject.Timestamp = value; }
}

/// <summary>
/// Gets or sets the entity's current ETag.
/// Set this value to '*' in order to blindly overwrite an entity as part of an update operation.
/// </summary>
public string ETag
{
get { return InnerObject.ETag; }
set { InnerObject.ETag = value; }
}

/// <summary>
/// Place holder for the original entity
/// </summary>
public T InnerObject { get; set; }
#endregion

#region Ctor
public AzureStorageEntityAdapter()
{
// If you would like to work with objects that do not have a default Ctor you can use (T)Activator.CreateInstance(typeof(T));
this.InnerObject = new T();
}

public AzureStorageEntityAdapter(T innerObject)
{
this.InnerObject = innerObject;
}
#endregion

#region Methods

public virtual void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
{
TableEntity.ReadUserObject(this.InnerObject, properties, operationContext);
}

public virtual IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
{
return TableEntity.WriteUserObject(this.InnerObject, operationContext);
}

#endregion
}

我希望能够做这样的事情......

public class TableStorageRepository : IRepository
{
// snip...

public IQueryable<T> FindAll<T>() where T : class, new()
{
CloudTable table = GetCloudTable<T>();
return table.CreateQuery<AzureStorageEntityAdapter<T>>();
}

// snip...
}

这里的问题是 CreateQuery 创建了一个

IQueryable<AzureStorageEntityApater<T>>.

我不知道如何获取所有“InnerObjects”的 IQueryable。

有人知道是否可以通过某种方式公开 IQueryable 而无需公开 ITableEntity?

最佳答案

这可能是也可能不是您想要的,但可能会给您一些想法。

我创建了一个基础存储库,并为每个实体使用了一个单独的存储库,该存储库负责传递正确的 CloudTable、分区/行键/属性表达式和解析器。我将其基于 DynamicTableEntity(它允许一些高级内容,例如动态属性)在我的实体中(例如小型集合))。

public class BaseRepository
{
protected async Task<DynamicTableEntity> GetAsync(CloudTable table, Expression<Func<DynamicTableEntity, bool>> filter)
{
var query = table.CreateQuery<DynamicTableEntity>().Where(filter).AsTableQuery();
var segment = await query.ExecuteSegmentedAsync(null);
return segment.Results.FirstOrDefault();
}

protected async Task<T> GetAsync<T>(CloudTable table, Expression<Func<DynamicTableEntity, bool>> filter, EntityResolver<T> resolver)
{
var query = table.CreateQuery<DynamicTableEntity>().Where(filter).Resolve(resolver);
var segment = await query.ExecuteSegmentedAsync(null);
return segment.Results.FirstOrDefault();
}

protected async Task<IEnumerable<DynamicTableEntity>> GetAllAsync(CloudTable table, Expression<Func<DynamicTableEntity, bool>> filter, int take = 1000)
{
if (take > 10000) take = 10000;
if (take < 1) take = 1;

var query = table.CreateQuery<DynamicTableEntity>().Where(filter).Take(take).AsTableQuery();
var token = new TableContinuationToken();
var results = new List<DynamicTableEntity>();
while (token != null)
{
var segment = await query.ExecuteSegmentedAsync(token);
results.AddRange(segment.Results);
token = segment.ContinuationToken;
}
return results;
}

protected async Task<IEnumerable<T>> GetAllAsync<T>(CloudTable table, Expression<Func<DynamicTableEntity, bool>> filter, EntityResolver<T> resolver, int take = 1000)
{
if (take > 10000) take = 10000;
if (take < 1) take = 1;

var query = table.CreateQuery<DynamicTableEntity>().Where(filter).Take(take).Resolve(resolver);
var token = new TableContinuationToken();
var results = new List<T>();
while (token != null)
{
var segment = await query.ExecuteSegmentedAsync(token);
results.AddRange(segment.Results);
token = segment.ContinuationToken;
}
return results;
}

protected async Task<int> InsertAsync(CloudTable table, DynamicTableEntity entity)
{
try
{
var result = await table.ExecuteAsync(TableOperation.Insert(entity));
return result.HttpStatusCode;
}
catch (StorageException ex)
{
return ex.RequestInformation.HttpStatusCode;
}
catch (Exception ex)
{
return 500;
}
}

protected async Task<int> ReplaceAsync(CloudTable table, DynamicTableEntity entity)
{
try
{
var result = await table.ExecuteAsync(TableOperation.Replace(entity));
return result.HttpStatusCode;
}
catch (StorageException ex)
{
return ex.RequestInformation.HttpStatusCode;
}
catch (Exception ex)
{
return 500;
}
}

protected async Task<int> DeleteAsync(CloudTable table, DynamicTableEntity entity)
{
try
{
var result = await table.ExecuteAsync(TableOperation.Delete(entity));
return result.HttpStatusCode;
}
catch (StorageException ex)
{
return ex.RequestInformation.HttpStatusCode;
}
catch (Exception ex)
{
return 500;
}
}

protected async Task<int> MergeAsync(CloudTable table, DynamicTableEntity entity)
{
try
{
var result = await table.ExecuteAsync(TableOperation.Merge(entity));
return result.HttpStatusCode;
}
catch (StorageException ex)
{
return ex.RequestInformation.HttpStatusCode;
}
catch (Exception ex)
{
return 500;
}
}
}

继承它的类的示例(您必须发挥想象力来填补空白 - 如果您想查看正确的实现,请告诉我)

// method
public Task<IEnumerable<T>> GetAllAsync<T>(string pk1, string pk2, EntityResolver<T> resolver, int take = 1000, Expression<Func<DynamicTableEntity, bool>> filterExpr = null)
{
var keysExpr = x => x.PartitionKey.Equals(string.Format("{0}_{1}", pk1, pk2);
var queryExpr = filterExpr != null ? keysExpr.AndAlso(filterExpr) : keysExpr;
return base.GetAllAsync<T>(CloudTableSelector.GetTable(), queryExpr, resolver, take);
}

// call
var products = await ProductRepo.GetAllAsync<ProductOwnerViewDto>(orgType, orgId, ProductOwnerViewDto.GetResolver(), take, x => x.RowKey.CompareTo(fromId) > 0);

将所有实体包装在单独的存储库中有点原始和痛苦,但我找不到一种方法让我以这种方式查询表,同时让我得到不同的投影(每个表有多个解析器) .

我找到了基于 ITableEntity 限制的解决方案(这很好,直到您需要动态属性,然后您就完蛋了)。

关于azure - 您可以将 Azure 表存储 IQueryable ( table.CreateQuery() ) 公开为 POCO 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33162412/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com