gpt4 book ai didi

c# - 支持按分区键查询而无需更改接口(interface)的存储库

转载 作者:行者123 更新时间:2023-12-03 14:31:42 24 4
gpt4 key购买 nike

我正在开发一个使用 IDocumentClient 的应用程序对 CosmosDB 执行查询。我的 GenericRepository支持Id查询和 Predicate .
将数据库从 SqlServer 更改为 CosmosDb 时遇到麻烦,在 CosmosDb 中,我们有 partition key .而且我不知道如何实现支持 partition key 查询的存储库无需更改接口(interface)即可通过partition key作为论据。

public interface IRepository<T>
{
//I can handle this one by adding value of partition key to id and split it by ":"
Task<T> FindByIdAsync(string id);

// I am stuck here!!!
Task<T> FindByPredicateAsync(Expression<Func<T, bool>> predicate);
}
我的实现
public class Repository<T> : IRepository<T>
{
private readonly IDocumentClient _documentClient;

private readonly string _databaseId;
private readonly string _collectionId;

public Repository(IDocumentClient documentClient, string databaseId, string collectionId)
{
_documentClient = documentClient;

_databaseId = databaseId;
_collectionId = collectionId;
}

public async Task<T> FindByIdAsync(string id)
{
var documentUri = UriFactory.CreateDocumentUri(_databaseId, _collectionId, id);

try
{
var result = await _documentClient.ReadDocumentAsync<TDocument>(documentUri, new RequestOptions
{
PartitionKey = ParsePartitionKey(documentId)
});

return result.Document;
}
catch (DocumentClientException e)
{
if (e.StatusCode == HttpStatusCode.NotFound)
{
throw new EntityNotFoundException();
}

throw;
}
}

public async Task<T> FindByPredicateAsync(Expression<Func<T, bool>> predicate)
{
//Need to query CosmosDb with partition key here!
}

private PartitionKey ParsePartitionKey(string entityId) => new PartitionKey(entityId.Split(':')[0]);
}
非常感谢任何帮助,谢谢。

最佳答案

我找到了使您的存储库独立于数据库的解决方案(例如,我使用的是 v3 SDK)。只是将当前界面分为两部分:

public interface IRepository<T>
{
Task<T> FindItemByDocumentIdAsync(string documentId);


Task<IEnumerable<T>> FindItemsBySqlTextAsync(string sqlQuery);

Task<IEnumerable<T>> FindAll(Expression<Func<T, bool>> predicate = null);
}

public interface IPartitionSetter<T>
{
string PartititonKeyValue { get; }

void SetPartitionKey<T>(string partitionKey);
}//using factory method or DI framework to create same instance for IRepository<T> and IPartitionSetter<T> in a http request
执行:
public class Repository<T> : IRepository<T>, IPartitionSetter<T>
{
//other implementation

public async Task<IEnumerable<T>> FindAll(Expression<Func<T, bool>> predicate = null)
{
var result = new List<T>();
var queryOptions = new QueryRequestOptions
{
MaxConcurrency = -1,
PartitionKey = ParsePartitionKey()
};

IQueryable<T> query = _container.GetItemLinqQueryable<T>(requestOptions: queryOptions);

if (predicate != null)
{
query = query.Where(predicate);
}

var setIterator = query.ToFeedIterator();
while (setIterator.HasMoreResults)
{
var executer = await setIterator.ReadNextAsync();

result.AddRange(executer.Resource);
}

return result;
}

private string _partitionKey;

public string PartititonKeyValue => _partitionKey;

private PartitionKey? ParsePartitionKey()
{
if (_partitionKey == null)
return null;
else if (_partitionKey == string.Empty)
return PartitionKey.None;//for query documents with partition key is empty
else
return new PartitionKey(_partitionKey);
}

public void SetPartitionKey<T>(string partitionKey)
{
_partitionKey = partitionKey;
}
}
您需要注入(inject) IPartitionSetter<T>并调用 SetPartitionKey在执行查询之前在这里应用分区键。

关于c# - 支持按分区键查询而无需更改接口(interface)的存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63573200/

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