Skip to content
This repository has been archived by the owner on Oct 7, 2023. It is now read-only.

Commit

Permalink
feat: rethrow DuplicateDatabaseEntityException if duplicate key
Browse files Browse the repository at this point in the history
* Rethrow Mongo/Cosmos exception as `DuplicateDatabaseEntityException` if it is a DuplicateKey/Conflict exception
* Rework `OrderExpressions` and `OrderTypeEnum`
  • Loading branch information
francoishill committed Mar 21, 2023
1 parent 2eface9 commit cdf6341
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish-nuget-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

env:
DOTNET_VERSION: '7.0'
PACKAGE_VERSION: "0.21.0"
PACKAGE_VERSION: "0.22.0"

jobs:
build-and-deploy:
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ namespace Firepuma.DatabaseRepositories.Abstractions.QuerySpecifications;

public enum OrderTypeEnum
{
OrderBy = 1,
OrderByDescending = 2,
ThenBy = 3,
ThenByDescending = 4
Ascending,
Descending,
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Firepuma.DatabaseRepositories.Abstractions.QuerySpecifications.Exceptions;

namespace Firepuma.DatabaseRepositories.Abstractions.QuerySpecifications;
namespace Firepuma.DatabaseRepositories.Abstractions.QuerySpecifications;

public abstract class QuerySpecificationEvaluatorBase<T> : IQuerySpecificationEvaluator<T> where T : class
{
Expand All @@ -22,29 +20,20 @@ public virtual IQueryable<T> GetQuery(IQueryable<T> inputQuery, IQuerySpecificat

if (querySpecification.OrderExpressions.Any())
{
if (querySpecification.OrderExpressions.Count(x => x.OrderType is OrderTypeEnum.OrderBy or OrderTypeEnum.OrderByDescending) > 1)
{
throw new DuplicateOrderChainException();
}

IOrderedQueryable<T>? orderedQuery = null;
foreach (var orderExpression in querySpecification.OrderExpressions)
{
if (orderExpression.OrderType == OrderTypeEnum.OrderBy)
{
orderedQuery = queryable.OrderBy(orderExpression.KeySelector);
}
else if (orderExpression.OrderType == OrderTypeEnum.OrderByDescending)
{
orderedQuery = queryable.OrderByDescending(orderExpression.KeySelector);
}
else if (orderExpression.OrderType == OrderTypeEnum.ThenBy)
if (orderedQuery == null)
{
orderedQuery = orderedQuery?.ThenBy(orderExpression.KeySelector);
orderedQuery = orderExpression.OrderType == OrderTypeEnum.Ascending
? queryable.OrderBy(orderExpression.KeySelector)
: queryable.OrderByDescending(orderExpression.KeySelector);
}
else if (orderExpression.OrderType == OrderTypeEnum.ThenByDescending)
else
{
orderedQuery = orderedQuery?.ThenByDescending(orderExpression.KeySelector);
orderedQuery = orderExpression.OrderType == OrderTypeEnum.Ascending
? orderedQuery.ThenBy(orderExpression.KeySelector)
: orderedQuery.ThenByDescending(orderExpression.KeySelector);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Firepuma.DatabaseRepositories.Abstractions.Repositories.Exceptions;

public class DuplicateDatabaseEntityException : Exception
{
public DuplicateDatabaseEntityException(string message, Exception innerException)
: base(message, innerException)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,8 @@

public class MultipleResultsInsteadOfSingleException : Exception
{
public MultipleResultsInsteadOfSingleException()
{
}

public MultipleResultsInsteadOfSingleException(string message)
: base(message)
{
}

public MultipleResultsInsteadOfSingleException(string message, Exception inner)
: base(message, inner)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,21 @@ public async Task<T> AddItemAsync(
"Will now add item id {Id} to container {Container}",
item.Id, Container.Id);

var response = await Container.CreateItemAsync<T>(item, ResolvePartitionKey(item.Id), cancellationToken: cancellationToken);
try
{
var response = await Container.CreateItemAsync<T>(item, ResolvePartitionKey(item.Id), cancellationToken: cancellationToken);

Logger.LogInformation(
"Added item id {Id} to container {Container}, which consumed {Charge} RUs",
item.Id, Container.Id, response.RequestCharge);
Logger.LogInformation(
"Added item id {Id} to container {Container}, which consumed {Charge} RUs",
item.Id, Container.Id, response.RequestCharge);

return response.Resource;
return response.Resource;
}
catch (CosmosException cosmosException) when (cosmosException.StatusCode == HttpStatusCode.Conflict)
{
//https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.documents.client.documentclient.upsertdocumentasync?view=azure-dotnet
throw new DuplicateDatabaseEntityException($"Duplicate id/key detected, unable to insert item with Id {item.Id}", cosmosException);
}
}

public async Task<T> ReplaceItemAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,20 @@ public async Task<T> AddItemAsync(T item, CancellationToken cancellationToken =
"Will now add item id {Id} to collection {Collection}",
item.Id, CollectionNameForLogs);

await Collection.InsertOneAsync(item, cancellationToken: cancellationToken);
try
{
await Collection.InsertOneAsync(item, cancellationToken: cancellationToken);

Logger.LogInformation(
"Added item id {Id} to collection {Collection}",
item.Id, CollectionNameForLogs);
Logger.LogInformation(
"Added item id {Id} to collection {Collection}",
item.Id, CollectionNameForLogs);

return item;
return item;
}
catch (MongoWriteException mongoWriteException) when (mongoWriteException.WriteError.Code == 11000)
{
throw new DuplicateDatabaseEntityException($"Duplicate id/key detected, unable to insert item with Id {item.Id}", mongoWriteException);
}
}

public async Task<T> ReplaceItemAsync(
Expand Down

0 comments on commit cdf6341

Please sign in to comment.