(feature): code review, tests and readme
This commit is contained in:
parent
b3edd3398d
commit
812d7b72d0
297
README.md
Normal file
297
README.md
Normal file
@ -0,0 +1,297 @@
|
||||
# MaksIT.MongoDB.Linq
|
||||
|
||||
## Description
|
||||
|
||||
`MaksIT.MongoDB.Linq` is a .NET library designed to facilitate working with MongoDB using LINQ queries, providing a seamless and intuitive interface for developers to interact with MongoDB databases. The library abstracts common data access patterns, allowing for more efficient and readable code when performing CRUD operations, managing sessions, and handling transactions.
|
||||
|
||||
## Purpose
|
||||
|
||||
The primary goal of `MaksIT.MongoDB.Linq` is to simplify MongoDB integration in .NET applications by offering a robust, easy-to-use API. Whether you're managing complex queries, handling transactions, or implementing custom data providers, this library enables developers to focus on business logic while abstracting the intricacies of MongoDB operations.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **LINQ Integration:** Query MongoDB collections using familiar LINQ syntax.
|
||||
- **CRUD Operations:** Simplified methods for creating, reading, updating, and deleting documents.
|
||||
- **Session and Transaction Management:** Built-in support for managing MongoDB sessions and transactions.
|
||||
- **Custom Data Providers:** Extendable base classes to create your own data providers.
|
||||
- **Error Handling:** Robust error handling with detailed logging using `Microsoft.Extensions.Logging`.
|
||||
- **Support for Comb GUIDs:** Generate sortable GUIDs with timestamps for improved query performance.
|
||||
|
||||
## Installation
|
||||
|
||||
To include `MaksIT.MongoDB.Linq` in your .NET project, you can add the package via NuGet:
|
||||
|
||||
```shell
|
||||
dotnet add package MaksIT.MongoDB.Linq
|
||||
```
|
||||
|
||||
> Note: This library utilizes the `MaksIT.Results` library to standardize result handling and error management. `MaksIT.Results` provides a robust framework for handling operation outcomes with appropriate HTTP status codes and seamless conversion to `IActionResult` for ASP.NET Core applications.
|
||||
>
|
||||
>For more information about `MaksIT.Results`, visit the [GitHub repository](https://github.com/MAKS-IT-COM/maksit-results).
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Creating a Custom Data Provider
|
||||
|
||||
Below is an example of a custom data provider that demonstrates CRUD operations using `MaksIT.MongoDB.Linq`.
|
||||
|
||||
```csharp
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
using MaksIT.Vault.Abstractions;
|
||||
using MaksIT.Core.Extensions; // Assuming this namespace contains the extension method ToNullable
|
||||
|
||||
public class OrganizationDataProvider : CollectionDataProviderBase<OrganizationDataProvider, OrganizationDto, Guid>, IOrganizationDataProvider
|
||||
{
|
||||
public OrganizationDataProvider(
|
||||
ILogger<OrganizationDataProvider> logger,
|
||||
IMongoClient client,
|
||||
IIdGenerator idGenerator
|
||||
) : base(logger, client, idGenerator, "maksit-vault", "organizations") { }
|
||||
|
||||
// **Read** operation: Get a document by ID
|
||||
public Result<OrganizationDto?> GetById(Guid id) =>
|
||||
GetWithPredicate(x => x.Id == id, x => x, null, null)
|
||||
.WithNewValue(_ => _?.FirstOrDefault());
|
||||
|
||||
// **Insert** operation: Insert a new document
|
||||
public Result<Guid?> Insert(OrganizationDto document, IClientSessionHandle? session = null) =>
|
||||
InsertAsync(document, session).Result
|
||||
.WithNewValue(_ => _.ToNullable());
|
||||
|
||||
// **InsertMany** operation: Insert multiple documents
|
||||
public Result<List<Guid>?> InsertMany(List<OrganizationDto> documents, IClientSessionHandle? session = null) =>
|
||||
InsertManyAsync(documents, session).Result
|
||||
.WithNewValue(_ => _?.Select(id => id.ToNullable()).ToList());
|
||||
|
||||
// **Update** operation: Update a document by a predicate
|
||||
public Result<Guid?> UpdateById(OrganizationDto document, IClientSessionHandle? session = null) =>
|
||||
UpdateWithPredicate(document, x => x.Id == document.Id, session)
|
||||
.WithNewValue(_ => _.ToNullable());
|
||||
|
||||
// **UpdateMany** operation: Update multiple documents by a predicate
|
||||
public Result<List<Guid>?> UpdateManyById(List<OrganizationDto> documents, IClientSessionHandle? session = null) =>
|
||||
UpdateManyWithPredicate(x => documents.Select(y => y.Id).Contains(x.Id), documents, session)
|
||||
.WithNewValue(_ => _?.Select(id => id.ToNullable()).ToList());
|
||||
|
||||
// **Upsert** operation: Insert or update a document by ID
|
||||
public Result<Guid?> UpsertById(OrganizationDto document, IClientSessionHandle? session = null) =>
|
||||
UpsertWithPredicate(document, x => x.Id == document.Id, session)
|
||||
.WithNewValue(_ => _.ToNullable());
|
||||
|
||||
// **UpsertMany** operation: Insert or update multiple documents
|
||||
public Result<List<Guid>?> UpsertManyById(List<OrganizationDto> documents, IClientSessionHandle? session = null) =>
|
||||
UpsertManyWithPredicate(documents, x => documents.Select(y => y.Id).Contains(x.Id), session)
|
||||
.WithNewValue(_ => _?.Select(id => id.ToNullable()).ToList());
|
||||
|
||||
// **Delete** operation: Delete a document by ID
|
||||
public Result DeleteById(Guid id, IClientSessionHandle? session = null) =>
|
||||
DeleteWithPredicate(x => x.Id == id, session);
|
||||
|
||||
// **DeleteMany** operation: Delete multiple documents by ID
|
||||
public Result DeleteManyById(List<Guid> ids, IClientSessionHandle? session = null) =>
|
||||
DeleteManyWithPredicate(x => ids.Contains(x.Id), session);
|
||||
}
|
||||
```
|
||||
|
||||
### Performing CRUD Operations
|
||||
|
||||
#### Inserting a Document
|
||||
|
||||
```csharp
|
||||
var document = new OrganizationDto
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "My Organization"
|
||||
};
|
||||
|
||||
var insertResult = organizationDataProvider.Insert(document);
|
||||
if (insertResult.IsSuccess)
|
||||
{
|
||||
Console.WriteLine($"Document inserted with ID: {insertResult.Value}");
|
||||
}
|
||||
```
|
||||
|
||||
#### Getting a Document by ID
|
||||
|
||||
```csharp
|
||||
var id = Guid.Parse("your-document-id-here");
|
||||
var getResult = organizationDataProvider.GetById(id);
|
||||
|
||||
if (getResult.IsSuccess)
|
||||
{
|
||||
Console.WriteLine($"Document retrieved: {getResult.Value?.Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Document not found.");
|
||||
}
|
||||
```
|
||||
|
||||
#### Updating a Document
|
||||
|
||||
```csharp
|
||||
var documentToUpdate = new OrganizationDto
|
||||
{
|
||||
Id = existingId,
|
||||
Name = "Updated Organization Name"
|
||||
};
|
||||
|
||||
var updateResult = organizationDataProvider.UpdateById(documentToUpdate);
|
||||
if (updateResult.IsSuccess)
|
||||
{
|
||||
Console.WriteLine($"Document updated with ID: {updateResult.Value}");
|
||||
}
|
||||
```
|
||||
|
||||
#### Deleting a Document
|
||||
|
||||
```csharp
|
||||
var deleteResult = organizationDataProvider.DeleteById(idToDelete);
|
||||
if (deleteResult.IsSuccess)
|
||||
{
|
||||
Console.WriteLine("Document deleted successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Failed to delete the document.");
|
||||
}
|
||||
```
|
||||
|
||||
Here is the section listing the available methods in `BaseCollectionDataProviderBase` and `CollectionDataProviderBase`:
|
||||
|
||||
### Available Methods
|
||||
|
||||
#### `BaseCollectionDataProviderBase<T, TDtoDocument, TDtoKey>`
|
||||
|
||||
- **Insert Operations**
|
||||
- `Task<Result<TDtoKey?>> InsertAsync(TDtoDocument document, IClientSessionHandle? session = null)`: Asynchronously inserts a new document.
|
||||
- `Task<Result<List<TDtoKey>?>> InsertManyAsync(List<TDtoDocument> documents, IClientSessionHandle? session = null)`: Asynchronously inserts multiple documents.
|
||||
|
||||
- **Update Operations**
|
||||
- `Task<Result<TDtoKey?>> UpdateWithPredicateAsync(TDtoDocument document, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Asynchronously updates a document matching the specified predicate.
|
||||
- `Task<Result<List<TDtoKey>?>> UpdateManyWithPredicateAsync(List<TDtoDocument> documents, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Asynchronously updates multiple documents matching the specified predicate.
|
||||
|
||||
- **Upsert Operations**
|
||||
- `Task<Result<TDtoKey?>> UpsertWithPredicateAsync(TDtoDocument document, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Asynchronously inserts or updates a document matching the specified predicate.
|
||||
- `Task<Result<List<TDtoKey>?>> UpsertManyWithPredicateAsync(List<TDtoDocument> documents, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Asynchronously inserts or updates multiple documents matching the specified predicate.
|
||||
|
||||
- **Delete Operations**
|
||||
- `Task<Result> DeleteWithPredicateAsync(Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Asynchronously deletes documents matching the specified predicate.
|
||||
- `Task<Result> DeleteManyWithPredicateAsync(Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Asynchronously deletes multiple documents matching the specified predicate.
|
||||
|
||||
#### `CollectionDataProviderBase<T, TDtoDocument, TDtoKey>`
|
||||
|
||||
- **Insert Operations**
|
||||
- `Result<TDtoKey?> Insert(TDtoDocument document, IClientSessionHandle? session = null)`: Inserts a new document.
|
||||
- `Result<List<TDtoKey>?> InsertMany(List<TDtoDocument> documents, IClientSessionHandle? session = null)`: Inserts multiple documents.
|
||||
|
||||
- **Read Operations**
|
||||
- `Result<List<TResult>?> GetWithPredicate<TResult>(Expression<Func<TDtoDocument, bool>> predicate, Expression<Func<TDtoDocument, TResult>> selector)`: Retrieves documents matching a predicate and projects them to a specified result type.
|
||||
- `Result<List<TResult>?> GetWithPredicate<TResult>(Expression<Func<TDtoDocument, bool>> predicate, Expression<Func<TDtoDocument, TResult>> selector, int? skip, int? limit)`: Retrieves documents matching a predicate, with optional skip and limit, and projects them to a specified result type.
|
||||
|
||||
- **Update Operations**
|
||||
- `Result<TDtoKey?> UpdateWithPredicate(TDtoDocument document, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Updates a document matching the specified predicate.
|
||||
- `Result<List<TDtoKey>?> UpdateManyWithPredicate(Expression<Func<TDtoDocument, bool>> predicate, List<TDtoDocument> documents, IClientSessionHandle? session = null)`: Updates multiple documents matching the specified predicate.
|
||||
|
||||
- **Upsert Operations**
|
||||
- `Result<TDtoKey?> UpsertWithPredicate(TDtoDocument document, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Inserts or updates a document matching the specified predicate.
|
||||
- `Result<List<TDtoKey>?> UpsertManyWithPredicate(List<TDtoDocument> documents, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Inserts or updates multiple documents matching the specified predicate.
|
||||
|
||||
- **Delete Operations**
|
||||
- `Result DeleteWithPredicate(Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Deletes documents matching the specified predicate.
|
||||
- `Result DeleteManyWithPredicate(Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session = null)`: Deletes multiple documents matching the specified predicate.
|
||||
|
||||
- **Count Operations**
|
||||
- `Result<int?> CountWithPredicate(Expression<Func<TDtoDocument, bool>> predicate)`: Counts documents matching a single predicate.
|
||||
- `Result<int?> CountWithPredicate(List<Expression<Func<TDtoDocument, bool>>> predicates)`: Counts documents matching multiple predicates.
|
||||
|
||||
These methods provide a comprehensive set of CRUD operations, allowing for flexible and powerful interaction with MongoDB databases through a LINQ-compatible interface.
|
||||
|
||||
No, the provided document did not mention the `CombGuidGenerator` utility from the `MaksIT.MongoDB.Linq.Utilities` namespace, which helps generate COMB GUIDs for collections.
|
||||
|
||||
To improve the documentation, here's an additional section that introduces the `CombGuidGenerator` utility:
|
||||
|
||||
---
|
||||
|
||||
## Additional Utilities
|
||||
|
||||
### `CombGuidGenerator`
|
||||
|
||||
The `MaksIT.MongoDB.Linq` library also includes a utility class `CombGuidGenerator` for generating COMB GUIDs (COMBined Globally Unique Identifiers) that incorporate both randomness and a timestamp. This is particularly useful for databases where sorting by the GUID is necessary, as it improves index efficiency and query performance.
|
||||
|
||||
#### Key Features
|
||||
|
||||
- **Combines GUID with Timestamp:** Provides better sortability in databases by embedding a timestamp into the GUID.
|
||||
- **Multiple Methods for Flexibility:** Supports generating COMB GUIDs with the current UTC timestamp, a specified timestamp, or a base GUID combined with a timestamp.
|
||||
|
||||
#### Usage Examples
|
||||
|
||||
```csharp
|
||||
using MaksIT.MongoDB.Linq.Utilities;
|
||||
|
||||
// Generate a COMB GUID using the current UTC timestamp
|
||||
Guid combGuid = CombGuidGenerator.CreateCombGuid();
|
||||
Console.WriteLine($"Generated COMB GUID: {combGuid}");
|
||||
|
||||
// Generate a COMB GUID from an existing GUID with the current UTC timestamp
|
||||
Guid baseGuid = Guid.NewGuid();
|
||||
Guid combGuidFromBase = CombGuidGenerator.CreateCombGuid(baseGuid);
|
||||
Console.WriteLine($"Generated COMB GUID from base GUID: {combGuidFromBase}");
|
||||
|
||||
// Generate a COMB GUID with a specific timestamp
|
||||
DateTime specificTimestamp = new DateTime(2024, 8, 31, 12, 0, 0, DateTimeKind.Utc);
|
||||
Guid combGuidWithTimestamp = CombGuidGenerator.CreateCombGuid(specificTimestamp);
|
||||
Console.WriteLine($"Generated COMB GUID with specific timestamp: {combGuidWithTimestamp}");
|
||||
|
||||
// Extract the embedded timestamp from a COMB GUID
|
||||
DateTime extractedTimestamp = CombGuidGenerator.ExtractTimestamp(combGuidWithTimestamp);
|
||||
Console.WriteLine($"Extracted Timestamp from COMB GUID: {extractedTimestamp}");
|
||||
```
|
||||
|
||||
### Benefits of Using COMB GUIDs
|
||||
|
||||
- **Improved Indexing Performance:** Embedding a timestamp in the GUID improves the indexing and retrieval performance of documents in databases, especially when using GUIDs as primary keys.
|
||||
- **Maintains Uniqueness with Sortability:** COMB GUIDs retain the uniqueness properties of traditional GUIDs while adding a sortable timestamp component, making them ideal for scenarios where both are needed.
|
||||
|
||||
By utilizing `CombGuidGenerator`, developers can ensure more efficient database operations when dealing with GUID-based identifiers in MongoDB collections.
|
||||
|
||||
## Contribution
|
||||
|
||||
Contributions to this project are welcome! Please fork the repository and submit a pull request with your changes. If you encounter any issues or have feature requests, feel free to open an issue on GitHub.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License. See the full license text below.
|
||||
|
||||
---
|
||||
|
||||
### MIT License
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Maksym Sadovnychyy (MAKS-IT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## Contact
|
||||
|
||||
For any questions or inquiries, please reach out via GitHub or [email](mailto:maksym.sadovnychyy@gmail.com).
|
||||
349
src/MaksIT.MongoDB.Linq.Tests/CollectionDataProviderBaseTests.cs
Normal file
349
src/MaksIT.MongoDB.Linq.Tests/CollectionDataProviderBaseTests.cs
Normal file
@ -0,0 +1,349 @@
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using MongoDB.Driver;
|
||||
|
||||
using MaksIT.Results;
|
||||
using MaksIT.MongoDB.Linq.Abstractions;
|
||||
using MaksIT.MongoDB.Linq.Abstractions.Domain;
|
||||
using MaksIT.MongoDB.Linq.Utilities;
|
||||
using MaksIT.MongoDB.Linq.Tests.Mock;
|
||||
|
||||
namespace MaksIT.MongoDB.Tests {
|
||||
|
||||
// Sample DTO class for testing
|
||||
public class TestableDocumentDto : DtoDocumentBase<Guid> {
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
|
||||
// Generalized Testable class to simulate MongoDB operations using an in-memory list
|
||||
public class TestableCollectionDataProvider : BaseCollectionDataProviderBase<TestableCollectionDataProvider, TestableDocumentDto, Guid> {
|
||||
private readonly List<TestableDocumentDto> _inMemoryCollection;
|
||||
|
||||
public TestableCollectionDataProvider(ILogger<TestableCollectionDataProvider> logger)
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
: base(logger, new MongoClientMock(), new MongoIdGeneratorMock(), "TestDatabase", "TestCollection") {
|
||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
_inMemoryCollection = new List<TestableDocumentDto>(); // Initialize correctly
|
||||
}
|
||||
|
||||
// Override protected methods to use in-memory list instead of a real database
|
||||
protected override IQueryable<TestableDocumentDto> GetQuery() => _inMemoryCollection.AsQueryable();
|
||||
|
||||
protected override async Task<Result<Guid>> InsertAsync(TestableDocumentDto document, IClientSessionHandle? session) {
|
||||
_inMemoryCollection.Add(document);
|
||||
return await Task.FromResult(Result<Guid>.Ok(document.Id));
|
||||
}
|
||||
|
||||
protected override async Task<Result<List<Guid>?>> InsertManyAsync(List<TestableDocumentDto> documents, IClientSessionHandle? session) {
|
||||
_inMemoryCollection.AddRange(documents);
|
||||
return await Task.FromResult(Result<List<Guid>?>.Ok(documents.Select(d => d.Id).ToList()));
|
||||
}
|
||||
|
||||
protected override async Task<Result<Guid>> UpsertWithPredicateAsync(TestableDocumentDto document, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session) {
|
||||
var existingDocument = _inMemoryCollection.FirstOrDefault(predicate.Compile());
|
||||
if (existingDocument != null) {
|
||||
_inMemoryCollection.Remove(existingDocument);
|
||||
}
|
||||
_inMemoryCollection.Add(document);
|
||||
return await Task.FromResult(Result<Guid>.Ok(document.Id));
|
||||
}
|
||||
|
||||
protected override async Task<Result<List<Guid>?>> UpsertManyWithPredicateAsync(List<TestableDocumentDto> documents, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session) {
|
||||
var existingDocuments = _inMemoryCollection.Where(predicate.Compile()).ToList();
|
||||
foreach (var doc in existingDocuments) {
|
||||
_inMemoryCollection.Remove(doc);
|
||||
}
|
||||
_inMemoryCollection.AddRange(documents);
|
||||
return await Task.FromResult(Result<List<Guid>?>.Ok(documents.Select(d => d.Id).ToList()));
|
||||
}
|
||||
|
||||
protected override async Task<Result<Guid>> UpdateWithPredicateAsync(TestableDocumentDto document, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session) {
|
||||
var existingDocument = _inMemoryCollection.FirstOrDefault(predicate.Compile());
|
||||
if (existingDocument != null) {
|
||||
_inMemoryCollection.Remove(existingDocument);
|
||||
_inMemoryCollection.Add(document);
|
||||
return await Task.FromResult(Result<Guid>.Ok(document.Id));
|
||||
}
|
||||
return await Task.FromResult(Result<Guid>.InternalServerError(default(Guid), "Update failed"));
|
||||
}
|
||||
|
||||
protected override async Task<Result<List<Guid>?>> UpdateManyWithPredicateAsync(List<TestableDocumentDto> documents, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session) {
|
||||
var existingDocuments = _inMemoryCollection.Where(predicate.Compile()).ToList();
|
||||
if (existingDocuments.Any()) {
|
||||
foreach (var doc in existingDocuments) {
|
||||
_inMemoryCollection.Remove(doc);
|
||||
}
|
||||
_inMemoryCollection.AddRange(documents);
|
||||
return await Task.FromResult(Result<List<Guid>?>.Ok(documents.Select(d => d.Id).ToList()));
|
||||
}
|
||||
return await Task.FromResult(Result<List<Guid>?>.InternalServerError(default, "UpdateMany failed"));
|
||||
}
|
||||
|
||||
protected override async Task<Result> DeleteWithPredicateAsync(Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session) {
|
||||
var documentToRemove = _inMemoryCollection.FirstOrDefault(predicate.Compile());
|
||||
if (documentToRemove != null) {
|
||||
_inMemoryCollection.Remove(documentToRemove);
|
||||
return await Task.FromResult(Result.Ok());
|
||||
}
|
||||
return await Task.FromResult(Result.InternalServerError("Delete failed"));
|
||||
}
|
||||
|
||||
protected override async Task<Result> DeleteManyWithPredicateAsync(Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session) {
|
||||
var documentsToRemove = _inMemoryCollection.Where(predicate.Compile()).ToList();
|
||||
if (documentsToRemove.Any()) {
|
||||
foreach (var doc in documentsToRemove) {
|
||||
_inMemoryCollection.Remove(doc);
|
||||
}
|
||||
return await Task.FromResult(Result.Ok());
|
||||
}
|
||||
return await Task.FromResult(Result.InternalServerError("DeleteMany failed"));
|
||||
}
|
||||
|
||||
// Expose protected methods as public with different names for testing purposes
|
||||
public async Task<Result<Guid>> TestInsertAsync(TestableDocumentDto document, IClientSessionHandle? session = null) {
|
||||
return await InsertAsync(document, session);
|
||||
}
|
||||
|
||||
public async Task<Result<List<Guid>?>> TestInsertManyAsync(List<TestableDocumentDto> documents, IClientSessionHandle? session = null) {
|
||||
return await InsertManyAsync(documents, session);
|
||||
}
|
||||
|
||||
public async Task<Result<Guid>> TestUpsertWithPredicateAsync(TestableDocumentDto document, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session = null) {
|
||||
return await UpsertWithPredicateAsync(document, predicate, session);
|
||||
}
|
||||
|
||||
public async Task<Result<List<Guid>?>> TestUpsertManyWithPredicateAsync(List<TestableDocumentDto> documents, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session = null) {
|
||||
return await UpsertManyWithPredicateAsync(documents, predicate, session);
|
||||
}
|
||||
|
||||
public async Task<Result<Guid>> TestUpdateWithPredicateAsync(TestableDocumentDto document, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session = null) {
|
||||
return await UpdateWithPredicateAsync(document, predicate, session);
|
||||
}
|
||||
|
||||
public async Task<Result<List<Guid>?>> TestUpdateManyWithPredicateAsync(List<TestableDocumentDto> documents, Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session = null) {
|
||||
return await UpdateManyWithPredicateAsync(documents, predicate, session);
|
||||
}
|
||||
|
||||
public async Task<Result> TestDeleteWithPredicateAsync(Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session = null) {
|
||||
return await DeleteWithPredicateAsync(predicate, session);
|
||||
}
|
||||
|
||||
public async Task<Result> TestDeleteManyWithPredicateAsync(Expression<Func<TestableDocumentDto, bool>> predicate, IClientSessionHandle? session = null) {
|
||||
return await DeleteManyWithPredicateAsync(predicate, session);
|
||||
}
|
||||
|
||||
// Helper method to access the in-memory collection for validation
|
||||
public IQueryable<TestableDocumentDto> GetInMemoryCollection() {
|
||||
return _inMemoryCollection.AsQueryable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class TestableCollectionDataProviderTests {
|
||||
private readonly TestableCollectionDataProvider _dataProvider;
|
||||
|
||||
public TestableCollectionDataProviderTests() {
|
||||
// Set up a mock logger
|
||||
var logger = new LoggerFactory().CreateLogger<TestableCollectionDataProvider>();
|
||||
_dataProvider = new TestableCollectionDataProvider(logger);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestInsertAsync_ShouldReturnOkResult_WhenDocumentIsInserted() {
|
||||
// Arrange
|
||||
var document = new TestableDocumentDto {
|
||||
Id = CombGuidGenerator.CreateCombGuid(),
|
||||
Name = "Test Document"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestInsertAsync(document, null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(document.Id, result.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestInsertManyAsync_ShouldReturnOkResult_WhenDocumentsAreInserted() {
|
||||
// Arrange
|
||||
var documents = new List<TestableDocumentDto>
|
||||
{
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 1" },
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 2" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestInsertManyAsync(documents, null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(2, result.Value?.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestUpsertWithPredicateAsync_ShouldInsertNewDocument_WhenNoMatchingDocumentExists() {
|
||||
// Arrange
|
||||
var document = new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Test Document" };
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestUpsertWithPredicateAsync(document, x => x.Id == document.Id, null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(document.Id, result.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestUpsertWithPredicateAsync_ShouldUpdateExistingDocument_WhenMatchingDocumentExists() {
|
||||
// Arrange
|
||||
var document = new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Initial Document" };
|
||||
await _dataProvider.TestInsertAsync(document, null);
|
||||
|
||||
var updatedDocument = new TestableDocumentDto { Id = document.Id, Name = "Updated Document" };
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestUpsertWithPredicateAsync(updatedDocument, x => x.Id == document.Id, null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(updatedDocument.Id, result.Value);
|
||||
|
||||
var inMemoryCollection = _dataProvider.GetInMemoryCollection().FirstOrDefault(x => x.Id == updatedDocument.Id);
|
||||
Assert.NotNull(inMemoryCollection);
|
||||
Assert.Equal("Updated Document", inMemoryCollection.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestUpsertManyWithPredicateAsync_ShouldInsertNewDocuments_WhenNoMatchingDocumentsExist() {
|
||||
// Arrange
|
||||
var documents = new List<TestableDocumentDto>
|
||||
{
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 1" },
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 2" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestUpsertManyWithPredicateAsync(documents, x => documents.Select(d => d.Id).Contains(x.Id), null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(2, result.Value?.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestUpdateWithPredicateAsync_ShouldUpdateDocument_WhenMatchingDocumentExists() {
|
||||
// Arrange
|
||||
var document = new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Initial Document" };
|
||||
await _dataProvider.TestInsertAsync(document, null);
|
||||
|
||||
var updatedDocument = new TestableDocumentDto { Id = document.Id, Name = "Updated Document" };
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestUpdateWithPredicateAsync(updatedDocument, x => x.Id == document.Id, null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(updatedDocument.Id, result.Value);
|
||||
|
||||
var inMemoryCollection = _dataProvider.GetInMemoryCollection().FirstOrDefault(x => x.Id == updatedDocument.Id);
|
||||
Assert.NotNull(inMemoryCollection);
|
||||
Assert.Equal("Updated Document", inMemoryCollection.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestUpdateManyWithPredicateAsync_ShouldUpdateDocuments_WhenMatchingDocumentsExist() {
|
||||
// Arrange
|
||||
var documents = new List<TestableDocumentDto>
|
||||
{
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 1" },
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 2" }
|
||||
};
|
||||
await _dataProvider.TestInsertManyAsync(documents, null);
|
||||
|
||||
var updatedDocuments = new List<TestableDocumentDto>
|
||||
{
|
||||
new TestableDocumentDto { Id = documents[0].Id, Name = "Updated Document 1" },
|
||||
new TestableDocumentDto { Id = documents[1].Id, Name = "Updated Document 2" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestUpdateManyWithPredicateAsync(updatedDocuments, x => updatedDocuments.Select(d => d.Id).Contains(x.Id), null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal(2, result.Value?.Count);
|
||||
|
||||
var inMemoryCollection = _dataProvider.GetInMemoryCollection().ToList();
|
||||
Assert.Equal("Updated Document 1", inMemoryCollection[0].Name);
|
||||
Assert.Equal("Updated Document 2", inMemoryCollection[1].Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestDeleteWithPredicateAsync_ShouldDeleteDocument_WhenMatchingDocumentExists() {
|
||||
// Arrange
|
||||
var document = new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Test Document" };
|
||||
await _dataProvider.TestInsertAsync(document, null);
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestDeleteWithPredicateAsync(x => x.Id == document.Id, null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
var inMemoryCollection = _dataProvider.GetInMemoryCollection().FirstOrDefault(x => x.Id == document.Id);
|
||||
Assert.Null(inMemoryCollection);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestDeleteManyWithPredicateAsync_ShouldDeleteDocuments_WhenMatchingDocumentsExist() {
|
||||
// Arrange
|
||||
var documents = new List<TestableDocumentDto>
|
||||
{
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 1" },
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 2" }
|
||||
};
|
||||
await _dataProvider.TestInsertManyAsync(documents, null);
|
||||
|
||||
// Act
|
||||
var result = await _dataProvider.TestDeleteManyWithPredicateAsync(x => documents.Select(d => d.Id).Contains(x.Id), null);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
var inMemoryCollection = _dataProvider.GetInMemoryCollection().ToList();
|
||||
Assert.Empty(inMemoryCollection);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestGetQuery_ShouldReturnCorrectDocuments() {
|
||||
// Arrange
|
||||
var documents = new List<TestableDocumentDto>
|
||||
{
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 1" },
|
||||
new TestableDocumentDto { Id = CombGuidGenerator.CreateCombGuid(), Name = "Document 2" }
|
||||
};
|
||||
|
||||
// Use 'await' to asynchronously wait for the operation
|
||||
await _dataProvider.TestInsertManyAsync(documents, null);
|
||||
|
||||
// Act
|
||||
var queryResult = _dataProvider.GetInMemoryCollection().ToList();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, queryResult.Count);
|
||||
Assert.Contains(queryResult, doc => doc.Name == "Document 1");
|
||||
Assert.Contains(queryResult, doc => doc.Name == "Document 2");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MaksIT.MongoDB.Linq\MaksIT.MongoDB.Linq.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
20
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoAsyncCursorMock.cs
Normal file
20
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoAsyncCursorMock.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests.Mock {
|
||||
internal class MongoAsyncCursorMock<T>(List<T> documents) : IAsyncCursor<T> {
|
||||
|
||||
public IEnumerable<T> Current => documents;
|
||||
|
||||
public bool MoveNext(CancellationToken cancellationToken = default) {
|
||||
return false; // Only one batch of data
|
||||
}
|
||||
|
||||
public Task<bool> MoveNextAsync(CancellationToken cancellationToken = default) {
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
175
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoClientMock.cs
Normal file
175
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoClientMock.cs
Normal file
@ -0,0 +1,175 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoDB.Driver.Core.Clusters;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests.Mock
|
||||
{
|
||||
internal class MongoClientMock : IMongoClient
|
||||
{
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
|
||||
public IMongoDatabase GetDatabase(string name, MongoDatabaseSettings settings = null)
|
||||
{
|
||||
return new MongoDatabaseMock();
|
||||
}
|
||||
|
||||
|
||||
public IClientSessionHandle StartSession(ClientSessionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new MongoSessionMock();
|
||||
}
|
||||
|
||||
public Task<IClientSessionHandle> StartSessionAsync(ClientSessionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult((IClientSessionHandle)new MongoSessionMock());
|
||||
}
|
||||
|
||||
#region not implemented
|
||||
|
||||
public ICluster Cluster => throw new NotImplementedException();
|
||||
|
||||
public MongoClientSettings Settings => throw new NotImplementedException();
|
||||
|
||||
public void DropDatabase(string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void DropDatabase(IClientSessionHandle session, string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DropDatabaseAsync(string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DropDatabaseAsync(IClientSessionHandle session, string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<string> ListDatabaseNames(CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<string> ListDatabaseNames(ListDatabaseNamesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<string> ListDatabaseNames(IClientSessionHandle session, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<string> ListDatabaseNames(IClientSessionHandle session, ListDatabaseNamesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<string>> ListDatabaseNamesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<string>> ListDatabaseNamesAsync(ListDatabaseNamesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<string>> ListDatabaseNamesAsync(IClientSessionHandle session, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<string>> ListDatabaseNamesAsync(IClientSessionHandle session, ListDatabaseNamesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<BsonDocument> ListDatabases(CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<BsonDocument> ListDatabases(ListDatabasesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<BsonDocument> ListDatabases(IClientSessionHandle session, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<BsonDocument> ListDatabases(IClientSessionHandle session, ListDatabasesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<BsonDocument>> ListDatabasesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<BsonDocument>> ListDatabasesAsync(ListDatabasesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<BsonDocument>> ListDatabasesAsync(IClientSessionHandle session, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<BsonDocument>> ListDatabasesAsync(IClientSessionHandle session, ListDatabasesOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IChangeStreamCursor<TResult> Watch<TResult>(PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IChangeStreamCursor<TResult> Watch<TResult>(IClientSessionHandle session, PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IChangeStreamCursor<TResult>> WatchAsync<TResult>(PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public Task<IChangeStreamCursor<TResult>> WatchAsync<TResult>(IClientSessionHandle session, PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public IMongoClient WithReadConcern(ReadConcern readConcern)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoClient WithReadPreference(ReadPreference readPreference)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoClient WithWriteConcern(WriteConcern writeConcern)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
}
|
||||
}
|
||||
506
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoCollectionMock.cs
Normal file
506
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoCollectionMock.cs
Normal file
@ -0,0 +1,506 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoDB.Driver.Search;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests.Mock
|
||||
{
|
||||
internal class MongoCollectionMock<TDocument> : IMongoCollection<TDocument>
|
||||
{
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
||||
#region not implemented
|
||||
public CollectionNamespace CollectionNamespace => throw new NotImplementedException();
|
||||
|
||||
public IMongoDatabase Database => throw new NotImplementedException();
|
||||
|
||||
public global::MongoDB.Bson.Serialization.IBsonSerializer<TDocument> DocumentSerializer => throw new NotImplementedException();
|
||||
|
||||
public IMongoIndexManager<TDocument> Indexes => throw new NotImplementedException();
|
||||
|
||||
public IMongoSearchIndexManager SearchIndexes => throw new NotImplementedException();
|
||||
|
||||
public MongoCollectionSettings Settings => throw new NotImplementedException();
|
||||
|
||||
public IAsyncCursor<TResult> Aggregate<TResult>(PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TResult> Aggregate<TResult>(IClientSessionHandle session, PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TResult>> AggregateAsync<TResult>(PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TResult>> AggregateAsync<TResult>(IClientSessionHandle session, PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AggregateToCollection<TResult>(PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AggregateToCollection<TResult>(IClientSessionHandle session, PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task AggregateToCollectionAsync<TResult>(PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task AggregateToCollectionAsync<TResult>(IClientSessionHandle session, PipelineDefinition<TDocument, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public BulkWriteResult<TDocument> BulkWrite(IEnumerable<WriteModel<TDocument>> requests, BulkWriteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public BulkWriteResult<TDocument> BulkWrite(IClientSessionHandle session, IEnumerable<WriteModel<TDocument>> requests, BulkWriteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<BulkWriteResult<TDocument>> BulkWriteAsync(IEnumerable<WriteModel<TDocument>> requests, BulkWriteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<BulkWriteResult<TDocument>> BulkWriteAsync(IClientSessionHandle session, IEnumerable<WriteModel<TDocument>> requests, BulkWriteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long Count(FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long Count(IClientSessionHandle session, FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<long> CountAsync(FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<long> CountAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long CountDocuments(FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long CountDocuments(IClientSessionHandle session, FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<long> CountDocumentsAsync(FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<long> CountDocumentsAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DeleteResult DeleteMany(FilterDefinition<TDocument> filter, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DeleteResult DeleteMany(FilterDefinition<TDocument> filter, DeleteOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DeleteResult DeleteMany(IClientSessionHandle session, FilterDefinition<TDocument> filter, DeleteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<DeleteResult> DeleteManyAsync(FilterDefinition<TDocument> filter, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<DeleteResult> DeleteManyAsync(FilterDefinition<TDocument> filter, DeleteOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<DeleteResult> DeleteManyAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, DeleteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DeleteResult DeleteOne(FilterDefinition<TDocument> filter, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DeleteResult DeleteOne(FilterDefinition<TDocument> filter, DeleteOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DeleteResult DeleteOne(IClientSessionHandle session, FilterDefinition<TDocument> filter, DeleteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<DeleteResult> DeleteOneAsync(FilterDefinition<TDocument> filter, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<DeleteResult> DeleteOneAsync(FilterDefinition<TDocument> filter, DeleteOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<DeleteResult> DeleteOneAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, DeleteOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TField> Distinct<TField>(FieldDefinition<TDocument, TField> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TField> Distinct<TField>(IClientSessionHandle session, FieldDefinition<TDocument, TField> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TField>> DistinctAsync<TField>(FieldDefinition<TDocument, TField> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TField>> DistinctAsync<TField>(IClientSessionHandle session, FieldDefinition<TDocument, TField> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TItem> DistinctMany<TItem>(FieldDefinition<TDocument, IEnumerable<TItem>> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TItem> DistinctMany<TItem>(IClientSessionHandle session, FieldDefinition<TDocument, IEnumerable<TItem>> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TItem>> DistinctManyAsync<TItem>(FieldDefinition<TDocument, IEnumerable<TItem>> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TItem>> DistinctManyAsync<TItem>(IClientSessionHandle session, FieldDefinition<TDocument, IEnumerable<TItem>> field, FilterDefinition<TDocument> filter, DistinctOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public long EstimatedDocumentCount(EstimatedDocumentCountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<long> EstimatedDocumentCountAsync(EstimatedDocumentCountOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TProjection>> FindAsync<TProjection>(FilterDefinition<TDocument> filter, FindOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TProjection>> FindAsync<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, FindOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TProjection FindOneAndDelete<TProjection>(FilterDefinition<TDocument> filter, FindOneAndDeleteOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TProjection FindOneAndDelete<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, FindOneAndDeleteOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TProjection> FindOneAndDeleteAsync<TProjection>(FilterDefinition<TDocument> filter, FindOneAndDeleteOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TProjection> FindOneAndDeleteAsync<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, FindOneAndDeleteOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TProjection FindOneAndReplace<TProjection>(FilterDefinition<TDocument> filter, TDocument replacement, FindOneAndReplaceOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TProjection FindOneAndReplace<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, TDocument replacement, FindOneAndReplaceOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TProjection> FindOneAndReplaceAsync<TProjection>(FilterDefinition<TDocument> filter, TDocument replacement, FindOneAndReplaceOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TProjection> FindOneAndReplaceAsync<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, TDocument replacement, FindOneAndReplaceOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TProjection FindOneAndUpdate<TProjection>(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, FindOneAndUpdateOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TProjection FindOneAndUpdate<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, FindOneAndUpdateOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TProjection> FindOneAndUpdateAsync<TProjection>(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, FindOneAndUpdateOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TProjection> FindOneAndUpdateAsync<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, FindOneAndUpdateOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TProjection> FindSync<TProjection>(FilterDefinition<TDocument> filter, FindOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TProjection> FindSync<TProjection>(IClientSessionHandle session, FilterDefinition<TDocument> filter, FindOptions<TDocument, TProjection> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InsertMany(IEnumerable<TDocument> documents, InsertManyOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InsertMany(IClientSessionHandle session, IEnumerable<TDocument> documents, InsertManyOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task InsertManyAsync(IEnumerable<TDocument> documents, InsertManyOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task InsertManyAsync(IClientSessionHandle session, IEnumerable<TDocument> documents, InsertManyOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InsertOne(TDocument document, InsertOneOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InsertOne(IClientSessionHandle session, TDocument document, InsertOneOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task InsertOneAsync(TDocument document, CancellationToken _cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task InsertOneAsync(TDocument document, InsertOneOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task InsertOneAsync(IClientSessionHandle session, TDocument document, InsertOneOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TResult> MapReduce<TResult>(BsonJavaScript map, BsonJavaScript reduce, MapReduceOptions<TDocument, TResult> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TResult> MapReduce<TResult>(IClientSessionHandle session, BsonJavaScript map, BsonJavaScript reduce, MapReduceOptions<TDocument, TResult> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TResult>> MapReduceAsync<TResult>(BsonJavaScript map, BsonJavaScript reduce, MapReduceOptions<TDocument, TResult> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TResult>> MapReduceAsync<TResult>(IClientSessionHandle session, BsonJavaScript map, BsonJavaScript reduce, MapReduceOptions<TDocument, TResult> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IFilteredMongoCollection<TDerivedDocument> OfType<TDerivedDocument>() where TDerivedDocument : TDocument
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ReplaceOneResult ReplaceOne(FilterDefinition<TDocument> filter, TDocument replacement, ReplaceOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ReplaceOneResult ReplaceOne(FilterDefinition<TDocument> filter, TDocument replacement, UpdateOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ReplaceOneResult ReplaceOne(IClientSessionHandle session, FilterDefinition<TDocument> filter, TDocument replacement, ReplaceOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ReplaceOneResult ReplaceOne(IClientSessionHandle session, FilterDefinition<TDocument> filter, TDocument replacement, UpdateOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ReplaceOneResult> ReplaceOneAsync(FilterDefinition<TDocument> filter, TDocument replacement, ReplaceOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ReplaceOneResult> ReplaceOneAsync(FilterDefinition<TDocument> filter, TDocument replacement, UpdateOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ReplaceOneResult> ReplaceOneAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, TDocument replacement, ReplaceOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ReplaceOneResult> ReplaceOneAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, TDocument replacement, UpdateOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public UpdateResult UpdateMany(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public UpdateResult UpdateMany(IClientSessionHandle session, FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<UpdateResult> UpdateManyAsync(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<UpdateResult> UpdateManyAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public UpdateResult UpdateOne(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public UpdateResult UpdateOne(IClientSessionHandle session, FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<UpdateResult> UpdateOneAsync(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<UpdateResult> UpdateOneAsync(IClientSessionHandle session, FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, UpdateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IChangeStreamCursor<TResult> Watch<TResult>(PipelineDefinition<ChangeStreamDocument<TDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IChangeStreamCursor<TResult> Watch<TResult>(IClientSessionHandle session, PipelineDefinition<ChangeStreamDocument<TDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IChangeStreamCursor<TResult>> WatchAsync<TResult>(PipelineDefinition<ChangeStreamDocument<TDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IChangeStreamCursor<TResult>> WatchAsync<TResult>(IClientSessionHandle session, PipelineDefinition<ChangeStreamDocument<TDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoCollection<TDocument> WithReadConcern(ReadConcern readConcern)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoCollection<TDocument> WithReadPreference(ReadPreference readPreference)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoCollection<TDocument> WithWriteConcern(WriteConcern writeConcern)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
}
|
||||
}
|
||||
271
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoDatabaseMock.cs
Normal file
271
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoDatabaseMock.cs
Normal file
@ -0,0 +1,271 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests.Mock
|
||||
{
|
||||
internal class MongoDatabaseMock : IMongoDatabase
|
||||
{
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
|
||||
public IAsyncCursor<string> ListCollectionNames(ListCollectionNamesOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new MongoAsyncCursorMock<string>(new List<string>() { "TestCollection" });
|
||||
}
|
||||
|
||||
public void CreateCollection(string name, CreateCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public IMongoCollection<TDocument> GetCollection<TDocument>(string name, MongoCollectionSettings settings = null)
|
||||
{
|
||||
return new MongoCollectionMock<TDocument>();
|
||||
}
|
||||
|
||||
#region not implemented
|
||||
|
||||
public IMongoCollection<BsonDocument> this[string name] => throw new NotImplementedException();
|
||||
|
||||
public IMongoClient Client => throw new NotImplementedException();
|
||||
|
||||
public DatabaseNamespace DatabaseNamespace => throw new NotImplementedException();
|
||||
|
||||
public MongoDatabaseSettings Settings => throw new NotImplementedException();
|
||||
|
||||
public IAsyncCursor<TResult> Aggregate<TResult>(PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<TResult> Aggregate<TResult>(IClientSessionHandle session, PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TResult>> AggregateAsync<TResult>(PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<TResult>> AggregateAsync<TResult>(IClientSessionHandle session, PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AggregateToCollection<TResult>(PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AggregateToCollection<TResult>(IClientSessionHandle session, PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task AggregateToCollectionAsync<TResult>(PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task AggregateToCollectionAsync<TResult>(IClientSessionHandle session, PipelineDefinition<NoPipelineInput, TResult> pipeline, AggregateOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void CreateCollection(IClientSessionHandle session, string name, CreateCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CreateCollectionAsync(string name, CreateCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CreateCollectionAsync(IClientSessionHandle session, string name, CreateCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void CreateView<TDocument, TResult>(string viewName, string viewOn, PipelineDefinition<TDocument, TResult> pipeline, CreateViewOptions<TDocument> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void CreateView<TDocument, TResult>(IClientSessionHandle session, string viewName, string viewOn, PipelineDefinition<TDocument, TResult> pipeline, CreateViewOptions<TDocument> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CreateViewAsync<TDocument, TResult>(string viewName, string viewOn, PipelineDefinition<TDocument, TResult> pipeline, CreateViewOptions<TDocument> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CreateViewAsync<TDocument, TResult>(IClientSessionHandle session, string viewName, string viewOn, PipelineDefinition<TDocument, TResult> pipeline, CreateViewOptions<TDocument> options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void DropCollection(string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void DropCollection(string name, DropCollectionOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void DropCollection(IClientSessionHandle session, string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void DropCollection(IClientSessionHandle session, string name, DropCollectionOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DropCollectionAsync(string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DropCollectionAsync(string name, DropCollectionOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DropCollectionAsync(IClientSessionHandle session, string name, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DropCollectionAsync(IClientSessionHandle session, string name, DropCollectionOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public IAsyncCursor<string> ListCollectionNames(IClientSessionHandle session, ListCollectionNamesOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<string>> ListCollectionNamesAsync(ListCollectionNamesOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<string>> ListCollectionNamesAsync(IClientSessionHandle session, ListCollectionNamesOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<BsonDocument> ListCollections(ListCollectionsOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncCursor<BsonDocument> ListCollections(IClientSessionHandle session, ListCollectionsOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<BsonDocument>> ListCollectionsAsync(ListCollectionsOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAsyncCursor<BsonDocument>> ListCollectionsAsync(IClientSessionHandle session, ListCollectionsOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RenameCollection(string oldName, string newName, RenameCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RenameCollection(IClientSessionHandle session, string oldName, string newName, RenameCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RenameCollectionAsync(string oldName, string newName, RenameCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RenameCollectionAsync(IClientSessionHandle session, string oldName, string newName, RenameCollectionOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TResult RunCommand<TResult>(Command<TResult> command, ReadPreference readPreference = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TResult RunCommand<TResult>(IClientSessionHandle session, Command<TResult> command, ReadPreference readPreference = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TResult> RunCommandAsync<TResult>(Command<TResult> command, ReadPreference readPreference = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TResult> RunCommandAsync<TResult>(IClientSessionHandle session, Command<TResult> command, ReadPreference readPreference = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IChangeStreamCursor<TResult> Watch<TResult>(PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IChangeStreamCursor<TResult> Watch<TResult>(IClientSessionHandle session, PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IChangeStreamCursor<TResult>> WatchAsync<TResult>(PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IChangeStreamCursor<TResult>> WatchAsync<TResult>(IClientSessionHandle session, PipelineDefinition<ChangeStreamDocument<BsonDocument>, TResult> pipeline, ChangeStreamOptions options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoDatabase WithReadConcern(ReadConcern readConcern)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoDatabase WithReadPreference(ReadPreference readPreference)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMongoDatabase WithWriteConcern(WriteConcern writeConcern)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
}
|
||||
}
|
||||
19
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoIdGeneratorMock.cs
Normal file
19
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoIdGeneratorMock.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using MongoDB.Bson.Serialization;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests.Mock {
|
||||
internal class MongoIdGeneratorMock : IIdGenerator {
|
||||
public Guid Generate() {
|
||||
return Guid.NewGuid();
|
||||
}
|
||||
|
||||
#region not implemented
|
||||
public object GenerateId(object container, object document) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsEmpty(object id) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
93
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoSessionMock.cs
Normal file
93
src/MaksIT.MongoDB.Linq.Tests/Mock/MongoSessionMock.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoDB.Driver.Core.Bindings;
|
||||
using MongoDB.Driver.Core.Clusters;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests {
|
||||
internal class MongoSessionMock : IClientSessionHandle {
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
|
||||
public bool IsInTransaction { get; private set; } = false;
|
||||
|
||||
|
||||
public void StartTransaction(TransactionOptions transactionOptions = null) {
|
||||
IsInTransaction = true;
|
||||
}
|
||||
|
||||
public Task StartTransactionAsync(TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default) {
|
||||
IsInTransaction = true;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void AbortTransaction(CancellationToken cancellationToken = default) {
|
||||
IsInTransaction = false;
|
||||
}
|
||||
|
||||
public Task AbortTransactionAsync(CancellationToken cancellationToken = default) {
|
||||
IsInTransaction = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void CommitTransaction(CancellationToken cancellationToken = default) {
|
||||
IsInTransaction = false;
|
||||
}
|
||||
|
||||
public Task CommitTransactionAsync(CancellationToken cancellationToken = default) {
|
||||
IsInTransaction = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
#region not implemented
|
||||
|
||||
public ClientSessionOptions Options => new ClientSessionOptions();
|
||||
|
||||
public IMongoClient Client => throw new NotImplementedException();
|
||||
|
||||
public ICluster Cluster => throw new NotImplementedException();
|
||||
|
||||
public CoreSessionHandle WrappedCoreSession => throw new NotImplementedException();
|
||||
|
||||
public BsonDocument ClusterTime => throw new NotImplementedException();
|
||||
|
||||
public BsonDocument OperationTime => throw new NotImplementedException();
|
||||
|
||||
public bool IsImplicit => throw new NotImplementedException();
|
||||
|
||||
BsonTimestamp IClientSession.OperationTime => throw new NotImplementedException();
|
||||
|
||||
public IServerSession ServerSession => throw new NotImplementedException();
|
||||
|
||||
ICoreSessionHandle IClientSession.WrappedCoreSession => throw new NotImplementedException();
|
||||
|
||||
public void Dispose() {
|
||||
// Simulate disposing of the session
|
||||
}
|
||||
|
||||
public IClientSessionHandle Fork() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AdvanceClusterTime(BsonDocument newClusterTime) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AdvanceOperationTime(BsonTimestamp newOperationTime) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public TResult WithTransaction<TResult>(Func<IClientSessionHandle, CancellationToken, TResult> callback, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public Task<TResult> WithTransactionAsync<TResult>(Func<IClientSessionHandle, CancellationToken, Task<TResult>> callbackAsync, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
}
|
||||
}
|
||||
66
src/MaksIT.MongoDB.Linq.Tests/MongoSessionManagerTests.cs
Normal file
66
src/MaksIT.MongoDB.Linq.Tests/MongoSessionManagerTests.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using MaksIT.Results;
|
||||
using MaksIT.MongoDB.Linq.Tests.Mock;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests {
|
||||
public class MongoSessionManagerTests {
|
||||
|
||||
private readonly MongoSessionManager _sessionManager;
|
||||
private readonly ILogger<MongoSessionManager> _logger;
|
||||
|
||||
public MongoSessionManagerTests() {
|
||||
_logger = new LoggerFactory().CreateLogger<MongoSessionManager>();
|
||||
var mockClient = new MongoClientMock();
|
||||
_sessionManager = new MongoSessionManager(_logger, mockClient);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteInSession_ShouldCommitTransaction_WhenActionSucceeds() {
|
||||
// Act
|
||||
var result = _sessionManager.ExecuteInSession(session => {
|
||||
// Simulate successful operation
|
||||
return Result.Ok();
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecuteInSession_ShouldAbortTransaction_WhenActionFails() {
|
||||
// Act
|
||||
var result = _sessionManager.ExecuteInSession(session => {
|
||||
// Simulate failed operation
|
||||
return Result.InternalServerError("Simulated failure");
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.False(result.IsSuccess);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteInSessionAsync_ShouldCommitTransaction_WhenActionSucceeds() {
|
||||
// Act
|
||||
var result = await _sessionManager.ExecuteInSessionAsync(async session => {
|
||||
// Simulate successful operation
|
||||
return await Task.FromResult(Result.Ok());
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.True(result.IsSuccess);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteInSessionAsync_ShouldAbortTransaction_WhenActionFails() {
|
||||
// Act
|
||||
var result = await _sessionManager.ExecuteInSessionAsync(async session => {
|
||||
// Simulate failed operation
|
||||
return await Task.FromResult(Result.InternalServerError("Simulated failure"));
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.False(result.IsSuccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
using MaksIT.MongoDB.Linq.Utilities;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Tests.Utilities {
|
||||
public class CombGuidGeneratorTests {
|
||||
[Fact]
|
||||
public void CreateCombGuid_WithCurrentTimestamp_ShouldGenerateGuid() {
|
||||
// Act
|
||||
Guid combGuid = CombGuidGenerator.CreateCombGuid();
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(Guid.Empty, combGuid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCombGuid_WithSpecificGuidAndCurrentTimestamp_ShouldEmbedTimestamp() {
|
||||
// Arrange
|
||||
Guid inputGuid = Guid.NewGuid();
|
||||
|
||||
// Act
|
||||
Guid combGuid = CombGuidGenerator.CreateCombGuid(inputGuid);
|
||||
DateTime extractedTimestamp = CombGuidGenerator.ExtractTimestamp(combGuid);
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(Guid.Empty, combGuid);
|
||||
Assert.True(extractedTimestamp <= DateTime.UtcNow, "The extracted timestamp should not be in the future.");
|
||||
Assert.True(extractedTimestamp >= DateTime.UtcNow.AddSeconds(-5), "The extracted timestamp should be recent.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCombGuid_WithSpecificTimestamp_ShouldGenerateGuidWithEmbeddedTimestamp() {
|
||||
// Arrange
|
||||
DateTime timestamp = new DateTime(2024, 8, 30, 12, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
// Act
|
||||
Guid combGuid = CombGuidGenerator.CreateCombGuid(timestamp);
|
||||
DateTime extractedTimestamp = CombGuidGenerator.ExtractTimestamp(combGuid);
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(Guid.Empty, combGuid);
|
||||
Assert.Equal(timestamp, extractedTimestamp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCombGuid_WithGuidAndSpecificTimestamp_ShouldGenerateGuidWithEmbeddedTimestamp() {
|
||||
// Arrange
|
||||
Guid inputGuid = Guid.NewGuid();
|
||||
DateTime timestamp = new DateTime(2024, 8, 30, 12, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
// Act
|
||||
Guid combGuid = CombGuidGenerator.CreateCombGuidWithTimestamp(inputGuid, timestamp);
|
||||
DateTime extractedTimestamp = CombGuidGenerator.ExtractTimestamp(combGuid);
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(Guid.Empty, combGuid);
|
||||
Assert.Equal(timestamp, extractedTimestamp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtractTimestamp_ShouldExtractCorrectTimestampFromCombGuid() {
|
||||
// Arrange
|
||||
DateTime timestamp = new DateTime(2024, 8, 30, 12, 0, 0, DateTimeKind.Utc);
|
||||
Guid combGuid = CombGuidGenerator.CreateCombGuid(timestamp);
|
||||
|
||||
// Act
|
||||
DateTime extractedTimestamp = CombGuidGenerator.ExtractTimestamp(combGuid);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(timestamp, extractedTimestamp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtractTimestamp_WithInvalidGuid_ShouldThrowException() {
|
||||
// Arrange
|
||||
Guid invalidGuid = Guid.NewGuid();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Record.Exception(() => CombGuidGenerator.ExtractTimestamp(invalidGuid));
|
||||
Assert.Null(exception); // Adjusted expectation based on behavior of `ExtractTimestamp` with a regular GUID
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/MaksIT.MongoDB.Linq.sln
Normal file
31
src/MaksIT.MongoDB.Linq.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34902.65
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaksIT.MongoDB.Linq", "MaksIT.MongoDB.Linq\MaksIT.MongoDB.Linq.csproj", "{468F9B3E-E84D-4D53-A1A8-035F1DC1B54F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaksIT.MongoDB.Linq.Tests", "MaksIT.MongoDB.Linq.Tests\MaksIT.MongoDB.Linq.Tests.csproj", "{E3873056-9167-4DC1-9937-C8ED01E7A2E1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{468F9B3E-E84D-4D53-A1A8-035F1DC1B54F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{468F9B3E-E84D-4D53-A1A8-035F1DC1B54F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{468F9B3E-E84D-4D53-A1A8-035F1DC1B54F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{468F9B3E-E84D-4D53-A1A8-035F1DC1B54F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E3873056-9167-4DC1-9937-C8ED01E7A2E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E3873056-9167-4DC1-9937-C8ED01E7A2E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E3873056-9167-4DC1-9937-C8ED01E7A2E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E3873056-9167-4DC1-9937-C8ED01E7A2E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {646794FB-CAB9-4D30-917C-05BFA4686696}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@ -1,22 +1,17 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using MongoDB.Bson.Serialization;
|
||||
using MongoDB.Driver;
|
||||
using MaksIT.MongoDBLinq.Abstractions;
|
||||
using MaksIT.MongoDBLinq.Abstractions.Domain;
|
||||
|
||||
using MaksIT.MongoDB.Linq.Abstractions.Domain;
|
||||
using MaksIT.Results;
|
||||
using MongoDB.Bson.Serialization;
|
||||
|
||||
|
||||
namespace MaksIT.Vault.Abstractions {
|
||||
|
||||
public abstract class BaseCollectionDataProviderBase<T, TDomainDocument> : DataProviderBase<T> where TDomainDocument : DtoDocumentBase {
|
||||
namespace MaksIT.MongoDB.Linq.Abstractions {
|
||||
public abstract class BaseCollectionDataProviderBase<T, TDtoDocument, TDtoKey> : DataProviderBase<T>
|
||||
where TDtoDocument : DtoDocumentBase<TDtoKey> {
|
||||
|
||||
protected readonly IIdGenerator IdGenerator;
|
||||
protected readonly IMongoCollection<TDomainDocument> Collection;
|
||||
|
||||
protected readonly IMongoCollection<TDtoDocument> Collection;
|
||||
protected readonly string _errorMessage = "MaksIT.MongoDB.Linq - Data provider error";
|
||||
|
||||
protected BaseCollectionDataProviderBase(
|
||||
@ -31,71 +26,77 @@ namespace MaksIT.Vault.Abstractions {
|
||||
if (!Database.ListCollectionNames().ToList().Contains(collectionName))
|
||||
Database.CreateCollection(collectionName);
|
||||
|
||||
Collection = Database.GetCollection<TDomainDocument>(collectionName);
|
||||
Collection = Database.GetCollection<TDtoDocument>(collectionName);
|
||||
}
|
||||
|
||||
#region Insert
|
||||
protected virtual async Task<Result<Guid?>> InsertAsync(TDomainDocument document, IClientSessionHandle? session) {
|
||||
protected virtual async Task<Result<TDtoKey?>> InsertAsync(TDtoDocument document, IClientSessionHandle? session) {
|
||||
try {
|
||||
if (session != null)
|
||||
await Collection.InsertOneAsync(session, document);
|
||||
else
|
||||
await Collection.InsertOneAsync(document);
|
||||
|
||||
return Result<Guid?>.Ok(document.Id);
|
||||
return Result<TDtoKey?>.Ok(document.Id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.LogError(ex, _errorMessage);
|
||||
return Result<Guid?>.InternalServerError(null, _errorMessage);
|
||||
return Result<TDtoKey?>.InternalServerError(default(TDtoKey?), _errorMessage);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region InsertMany
|
||||
protected virtual async Task<Result<List<Guid>?>> InsertManyAsync(List<TDomainDocument> documents, IClientSessionHandle? session) {
|
||||
protected virtual async Task<Result<List<TDtoKey>?>> InsertManyAsync(List<TDtoDocument> documents, IClientSessionHandle? session) {
|
||||
try {
|
||||
if (session != null)
|
||||
await Collection.InsertManyAsync(session, documents);
|
||||
else
|
||||
await Collection.InsertManyAsync(documents);
|
||||
|
||||
return Result<List<Guid>?>.Ok(documents.Select(x => x.Id).ToList());
|
||||
return Result<List<TDtoKey>?>.Ok(documents.Select(x => x.Id).ToList());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.LogError(ex, _errorMessage);
|
||||
return Result<List<Guid>?>.InternalServerError(null, _errorMessage);
|
||||
return Result<List<TDtoKey>?>.InternalServerError(default, _errorMessage);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
protected virtual IQueryable<TDomainDocument> GetQuery() => Collection.AsQueryable();
|
||||
protected virtual IQueryable<TDtoDocument> GetQuery() => Collection.AsQueryable();
|
||||
#endregion
|
||||
|
||||
#region Update
|
||||
protected virtual async Task<Result<Guid?>> UpdateWithPredicateAsync(TDomainDocument document, Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) {
|
||||
protected virtual async Task<Result<TDtoKey?>> UpdateWithPredicateAsync(
|
||||
TDtoDocument document,
|
||||
Expression<Func<TDtoDocument, bool>> predicate,
|
||||
IClientSessionHandle? session) {
|
||||
try {
|
||||
if (session != null)
|
||||
await Collection.ReplaceOneAsync(session, predicate, document);
|
||||
else
|
||||
await Collection.ReplaceOneAsync(predicate, document);
|
||||
|
||||
return Result<Guid?>.Ok(document.Id);
|
||||
return Result<TDtoKey?>.Ok(document.Id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.LogError(ex, _errorMessage);
|
||||
return Result<Guid?>.InternalServerError(null, _errorMessage);
|
||||
return Result<TDtoKey?>.InternalServerError(default(TDtoKey?), _errorMessage);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UdateMany
|
||||
protected virtual async Task<Result<List<Guid>?>> UpdateManyWithPredicateAsync(List<TDomainDocument> documents, Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) {
|
||||
#region UpdateMany
|
||||
protected virtual async Task<Result<List<TDtoKey>?>> UpdateManyWithPredicateAsync(
|
||||
List<TDtoDocument> documents,
|
||||
Expression<Func<TDtoDocument, bool>> predicate,
|
||||
IClientSessionHandle? session) {
|
||||
try {
|
||||
var tasks = new List<Task<ReplaceOneResult>>();
|
||||
|
||||
foreach (var document in documents) {
|
||||
var filter = Builders<TDomainDocument>.Filter.Where(predicate);
|
||||
var filter = Builders<TDtoDocument>.Filter.Where(predicate);
|
||||
var updateOptions = new ReplaceOptions { IsUpsert = false };
|
||||
|
||||
if (session != null)
|
||||
@ -107,43 +108,48 @@ namespace MaksIT.Vault.Abstractions {
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
var upsertedIds = documents.Select(doc => doc.Id).ToList();
|
||||
return Result<List<Guid>?>.Ok(upsertedIds);
|
||||
return Result<List<TDtoKey>?>.Ok(upsertedIds);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.LogError(ex, _errorMessage);
|
||||
return Result<List<Guid>?>.InternalServerError(null, _errorMessage);
|
||||
return Result<List<TDtoKey>?>.InternalServerError(default, _errorMessage);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Upsert
|
||||
protected virtual async Task<Result<Guid?>> UpsertWithPredicateAsync(TDomainDocument documents, Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) {
|
||||
protected virtual async Task<Result<TDtoKey?>> UpsertWithPredicateAsync(
|
||||
TDtoDocument document,
|
||||
Expression<Func<TDtoDocument, bool>> predicate,
|
||||
IClientSessionHandle? session
|
||||
) {
|
||||
try {
|
||||
var updateOptions = new ReplaceOptions {
|
||||
IsUpsert = true
|
||||
};
|
||||
var updateOptions = new ReplaceOptions { IsUpsert = true };
|
||||
|
||||
if (session != null)
|
||||
await Collection.ReplaceOneAsync(session, predicate, documents, updateOptions);
|
||||
await Collection.ReplaceOneAsync(session, predicate, document, updateOptions);
|
||||
else
|
||||
await Collection.ReplaceOneAsync(predicate, documents, updateOptions);
|
||||
await Collection.ReplaceOneAsync(predicate, document, updateOptions);
|
||||
|
||||
return Result<Guid?>.Ok(documents.Id);
|
||||
return Result<TDtoKey?>.Ok(document.Id);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.LogError(ex, _errorMessage);
|
||||
return Result<Guid?>.InternalServerError(null, _errorMessage);
|
||||
return Result<TDtoKey?>.InternalServerError(default(TDtoKey?), _errorMessage);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpsertMany
|
||||
protected virtual async Task<Result<List<Guid>?>> UpsertManyWithPredicateAsync(List<TDomainDocument> documents, Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) {
|
||||
protected virtual async Task<Result<List<TDtoKey>?>> UpsertManyWithPredicateAsync(
|
||||
List<TDtoDocument> documents,
|
||||
Expression<Func<TDtoDocument, bool>> predicate,
|
||||
IClientSessionHandle? session) {
|
||||
try {
|
||||
var tasks = new List<Task<ReplaceOneResult>>();
|
||||
|
||||
foreach (var document in documents) {
|
||||
var filter = Builders<TDomainDocument>.Filter.Where(predicate);
|
||||
var filter = Builders<TDtoDocument>.Filter.Where(predicate);
|
||||
var updateOptions = new ReplaceOptions { IsUpsert = true };
|
||||
|
||||
if (session != null)
|
||||
@ -155,17 +161,19 @@ namespace MaksIT.Vault.Abstractions {
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
var upsertedIds = documents.Select(doc => doc.Id).ToList();
|
||||
return Result<List<Guid>?>.Ok(upsertedIds);
|
||||
return Result<List<TDtoKey>?>.Ok(upsertedIds);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.LogError(ex, _errorMessage);
|
||||
return Result<List<Guid>?>.InternalServerError(null, _errorMessage);
|
||||
return Result<List<TDtoKey>?>.InternalServerError(default, _errorMessage);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
protected virtual async Task<Result> DeleteWithPredicateAsync(Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) {
|
||||
protected virtual async Task<Result> DeleteWithPredicateAsync(
|
||||
Expression<Func<TDtoDocument, bool>> predicate,
|
||||
IClientSessionHandle? session) {
|
||||
try {
|
||||
if (session != null)
|
||||
await Collection.DeleteOneAsync(session, predicate);
|
||||
@ -182,7 +190,9 @@ namespace MaksIT.Vault.Abstractions {
|
||||
#endregion
|
||||
|
||||
#region DeleteMany
|
||||
protected virtual async Task<Result> DeleteManyWithPredicateAsync(Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) {
|
||||
protected virtual async Task<Result> DeleteManyWithPredicateAsync(
|
||||
Expression<Func<TDtoDocument, bool>> predicate,
|
||||
IClientSessionHandle? session) {
|
||||
try {
|
||||
if (session != null)
|
||||
await Collection.DeleteManyAsync(session, predicate);
|
||||
|
||||
@ -5,13 +5,14 @@ using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
using MongoDB.Bson.Serialization;
|
||||
|
||||
using MaksIT.MongoDBLinq.Abstractions.Domain;
|
||||
using MaksIT.MongoDB.Linq.Abstractions.Domain;
|
||||
|
||||
using MaksIT.Results;
|
||||
|
||||
namespace MaksIT.Vault.Abstractions {
|
||||
namespace MaksIT.MongoDB.Linq.Abstractions {
|
||||
|
||||
public abstract class CollectionDataProviderBase<T, TDomainDocument> : BaseCollectionDataProviderBase<T, TDomainDocument> where TDomainDocument : DtoDocumentBase {
|
||||
public abstract class CollectionDataProviderBase<T, TDtoDocument, TDtoKey> : BaseCollectionDataProviderBase<T, TDtoDocument, TDtoKey>
|
||||
where TDtoDocument : DtoDocumentBase<TDtoKey> {
|
||||
|
||||
protected CollectionDataProviderBase(
|
||||
ILogger<T> logger,
|
||||
@ -22,20 +23,20 @@ namespace MaksIT.Vault.Abstractions {
|
||||
) : base(logger, client, idGenerator, databaseName, collectionName) { }
|
||||
|
||||
#region Insert
|
||||
public Result<Guid?> Insert(TDomainDocument obj, IClientSessionHandle? session) =>
|
||||
public Result<TDtoKey?> Insert(TDtoDocument obj, IClientSessionHandle? session) =>
|
||||
InsertAsync(obj, session).Result;
|
||||
#endregion
|
||||
|
||||
#region InsertMany
|
||||
public Result<List<Guid>?> InsertMany(List<TDomainDocument> objList, IClientSessionHandle? session) =>
|
||||
public Result<List<TDtoKey>?> InsertMany(List<TDtoDocument> objList, IClientSessionHandle? session) =>
|
||||
InsertManyAsync(objList, session).Result;
|
||||
#endregion
|
||||
|
||||
#region Count
|
||||
protected Result<int?> CountWithPredicate(Expression<Func<TDomainDocument, bool>> predicate) =>
|
||||
CountWithPredicate(new List<Expression<Func<TDomainDocument, bool>>> { predicate });
|
||||
protected Result<int?> CountWithPredicate(Expression<Func<TDtoDocument, bool>> predicate) =>
|
||||
CountWithPredicate(new List<Expression<Func<TDtoDocument, bool>>> { predicate });
|
||||
|
||||
private protected Result<int?> CountWithPredicate(List<Expression<Func<TDomainDocument, bool>>> predicates) {
|
||||
private protected Result<int?> CountWithPredicate(List<Expression<Func<TDtoDocument, bool>>> predicates) {
|
||||
try {
|
||||
var query = GetWithPredicate(predicates);
|
||||
|
||||
@ -51,13 +52,19 @@ namespace MaksIT.Vault.Abstractions {
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
protected Result<List<TResult>?> GetWithPredicate<TResult>(Expression<Func<TDomainDocument, bool>> predicate, Expression<Func<TDomainDocument, TResult>> selector) =>
|
||||
GetWithPredicate(new List<Expression<Func<TDomainDocument, bool>>> { predicate }, selector, null, null);
|
||||
protected Result<List<TResult>?> GetWithPredicate<TResult>(Expression<Func<TDtoDocument, bool>> predicate, Expression<Func<TDtoDocument, TResult>> selector) =>
|
||||
GetWithPredicate(new List<Expression<Func<TDtoDocument, bool>>> { predicate }, selector, null, null);
|
||||
|
||||
protected Result<List<TResult>?> GetWithPredicate<TResult>(Expression<Func<TDomainDocument, bool>> predicate, Expression<Func<TDomainDocument, TResult>> selector, int? skip, int? limit) =>
|
||||
GetWithPredicate(new List<Expression<Func<TDomainDocument, bool>>> { predicate }, selector, skip, limit);
|
||||
protected Result<List<TResult>?> GetWithPredicate<TResult>(Expression<Func<TDtoDocument, bool>> predicate, Expression<Func<TDtoDocument, TResult>> selector, int? skip, int? limit) =>
|
||||
GetWithPredicate(new List<Expression<Func<TDtoDocument, bool>>> { predicate }, selector, skip, limit);
|
||||
|
||||
protected Result<List<TResult>?> GetWithPredicate<TResult>(
|
||||
List<Expression<Func<TDtoDocument, bool>>> predicates,
|
||||
Expression<Func<TDtoDocument, TResult>> selector,
|
||||
int? skip,
|
||||
int? limit
|
||||
) {
|
||||
|
||||
protected Result<List<TResult>?> GetWithPredicate<TResult>(List<Expression<Func<TDomainDocument, bool>>> predicates, Expression<Func<TDomainDocument, TResult>> selector, int? skip, int? limit) {
|
||||
try {
|
||||
var query = GetWithPredicate(predicates).Select(selector);
|
||||
|
||||
@ -79,7 +86,7 @@ namespace MaksIT.Vault.Abstractions {
|
||||
}
|
||||
}
|
||||
|
||||
protected IQueryable<TDomainDocument> GetWithPredicate(List<Expression<Func<TDomainDocument, bool>>> predicates) {
|
||||
protected IQueryable<TDtoDocument> GetWithPredicate(List<Expression<Func<TDtoDocument, bool>>> predicates) {
|
||||
var query = GetQuery();
|
||||
|
||||
foreach (var predicate in predicates)
|
||||
@ -90,32 +97,32 @@ namespace MaksIT.Vault.Abstractions {
|
||||
#endregion
|
||||
|
||||
#region Update
|
||||
protected Result<Guid?> UpdateWithPredicate(TDomainDocument obj, Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
protected Result<TDtoKey?> UpdateWithPredicate(TDtoDocument obj, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
UpdateWithPredicateAsync(obj, predicate, session).Result;
|
||||
#endregion
|
||||
|
||||
#region UpdateMany
|
||||
public Result<List<Guid>?> UpdateManyWithPredicate(Expression<Func<TDomainDocument, bool>> predicate, List<TDomainDocument> objList, IClientSessionHandle? session) =>
|
||||
public Result<List<TDtoKey>?> UpdateManyWithPredicate(Expression<Func<TDtoDocument, bool>> predicate, List<TDtoDocument> objList, IClientSessionHandle? session) =>
|
||||
UpdateManyWithPredicateAsync(objList, predicate, session).Result;
|
||||
#endregion
|
||||
|
||||
#region Upsert
|
||||
protected Result<Guid?> UpsertWithPredicate(TDomainDocument obj, Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
protected Result<TDtoKey?> UpsertWithPredicate(TDtoDocument obj, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
UpsertWithPredicateAsync(obj, predicate, session).Result;
|
||||
#endregion
|
||||
|
||||
#region UpsertMany
|
||||
public Result<List<Guid>?> UpsertManyWithPredicate(List<TDomainDocument> objList, Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
public Result<List<TDtoKey>?> UpsertManyWithPredicate(List<TDtoDocument> objList, Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
UpsertManyWithPredicateAsync(objList, predicate, session).Result;
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
protected Result DeleteWithPredicate(Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
protected Result DeleteWithPredicate(Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
DeleteWithPredicateAsync(predicate, session).Result;
|
||||
#endregion
|
||||
|
||||
#region DeleteMany
|
||||
protected Result DeleteManyWithPredicate(Expression<Func<TDomainDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
protected Result DeleteManyWithPredicate(Expression<Func<TDtoDocument, bool>> predicate, IClientSessionHandle? session) =>
|
||||
DeleteManyWithPredicateAsync(predicate, session).Result;
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -1,22 +1,19 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace MaksIT.MongoDBLinq.Abstractions {
|
||||
namespace MaksIT.MongoDB.Linq.Abstractions {
|
||||
public abstract class DataProviderBase<T> {
|
||||
protected readonly ILogger<T> Logger;
|
||||
protected readonly IMongoDatabase Database;
|
||||
|
||||
private readonly IMongoClient _client;
|
||||
|
||||
|
||||
protected DataProviderBase(
|
||||
ILogger<T> logger,
|
||||
IMongoClient client,
|
||||
string databaseName) {
|
||||
Logger = logger;
|
||||
|
||||
_client = client;
|
||||
Database = _client.GetDatabase(databaseName);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace MaksIT.MongoDB.Linq.Abstractions.Domain;
|
||||
|
||||
namespace MaksIT.MongoDBLinq.Abstractions.Domain {
|
||||
public abstract class DtoDocumentBase : DtoObjectBase {
|
||||
public Guid Id { get; set; }
|
||||
}
|
||||
public abstract class DtoDocumentBase<T> : DtoObjectBase {
|
||||
public required T Id { get; set; }
|
||||
}
|
||||
|
||||
@ -4,6 +4,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.MongoDBLinq.Abstractions.Domain {
|
||||
namespace MaksIT.MongoDB.Linq.Abstractions.Domain;
|
||||
public abstract class DtoObjectBase { }
|
||||
}
|
||||
|
||||
|
||||
@ -4,14 +4,26 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<RootNamespace>MaksIT.$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.28.0" />
|
||||
</ItemGroup>
|
||||
<!-- NuGet package metadata -->
|
||||
<PackageId>MaksIT.MongoDB.Linq</PackageId>
|
||||
<Version>1.0.0</Version>
|
||||
<Authors>Maksym Sadovnychyy</Authors>
|
||||
<Company>MAKS-IT</Company>
|
||||
<Product>MaksIT.MongoDB.Linq</Product>
|
||||
<Description></Description>
|
||||
<PackageTags></PackageTags>
|
||||
<RepositoryUrl>https://github.com/MAKS-IT-COM/maksit-mongodb-linq</RepositoryUrl>
|
||||
<License>MIT</License>
|
||||
<RequireLicenseAcceptance>false</RequireLicenseAcceptance>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\maksit-results\src\MaksIT.Results\MaksIT.Results.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MaksIT.Results" Version="1.0.0" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.28.0" />
|
||||
<None Include="../../README.md" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
using MongoDB.Driver;
|
||||
using System.Collections.Concurrent;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using MongoDB.Driver;
|
||||
using MaksIT.Results;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq {
|
||||
public interface IMongoSessionManager {
|
||||
Task<DisposableMongoSession> GetOrCreateSessionAsync();
|
||||
void ReleaseSession(DisposableMongoSession session);
|
||||
Result ExecuteInSession(Func<IClientSessionHandle, Result> action);
|
||||
Task<Result> ExecuteInSessionAsync(Func<IClientSessionHandle, Task<Result>> action);
|
||||
Result<T> ExecuteInSession<T>(Func<IClientSessionHandle, Result<T>> action);
|
||||
Task<Result<T>> ExecuteInSessionAsync<T>(Func<IClientSessionHandle, Task<Result<T>>> action);
|
||||
}
|
||||
|
||||
public class MongoSessionManager : IMongoSessionManager {
|
||||
@ -21,7 +22,7 @@ namespace MaksIT.MongoDB.Linq {
|
||||
_sessions = new ConcurrentDictionary<string, DisposableMongoSession>();
|
||||
}
|
||||
|
||||
public async Task<DisposableMongoSession> GetOrCreateSessionAsync() {
|
||||
private async Task<DisposableMongoSession> GetOrCreateSessionAsync() {
|
||||
// Generate a unique session ID
|
||||
var sessionId = Guid.NewGuid().ToString();
|
||||
|
||||
@ -43,7 +44,7 @@ namespace MaksIT.MongoDB.Linq {
|
||||
throw new InvalidOperationException("Failed to create or retrieve session.");
|
||||
}
|
||||
|
||||
public void ReleaseSession(DisposableMongoSession session) {
|
||||
private void ReleaseSession(DisposableMongoSession session) {
|
||||
if (_sessions.TryRemove(session.SessionId, out var _)) {
|
||||
_logger.LogInformation("Releasing and disposing session with ID: {SessionId}", session.SessionId);
|
||||
session.Dispose();
|
||||
@ -52,5 +53,114 @@ namespace MaksIT.MongoDB.Linq {
|
||||
_logger.LogWarning("Failed to find session with ID: {SessionId} for release.", session.SessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public Result ExecuteInSession(Func<IClientSessionHandle, Result> action) {
|
||||
using var mongoSession = GetOrCreateSessionAsync().Result;
|
||||
|
||||
try {
|
||||
mongoSession.Session.StartTransaction();
|
||||
var result = action(mongoSession.Session);
|
||||
|
||||
if (!result.IsSuccess) {
|
||||
mongoSession.Session.AbortTransaction();
|
||||
}
|
||||
else {
|
||||
mongoSession.Session.CommitTransaction();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.LogError(ex, "Error during session operation.");
|
||||
return Result.InternalServerError("An error occurred during the operation.");
|
||||
}
|
||||
finally {
|
||||
ReleaseSession(mongoSession);
|
||||
_logger.LogInformation("Session released for session ID: {SessionId}", mongoSession.SessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result> ExecuteInSessionAsync(Func<IClientSessionHandle, Task<Result>> action) {
|
||||
using var mongoSession = await GetOrCreateSessionAsync();
|
||||
|
||||
try {
|
||||
mongoSession.Session.StartTransaction();
|
||||
var result = await action(mongoSession.Session);
|
||||
|
||||
if (!result.IsSuccess) {
|
||||
await mongoSession.Session.AbortTransactionAsync();
|
||||
}
|
||||
else {
|
||||
await mongoSession.Session.CommitTransactionAsync();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.LogError(ex, "Error during async session operation.");
|
||||
return Result.InternalServerError("An error occurred during the async operation.");
|
||||
}
|
||||
finally {
|
||||
ReleaseSession(mongoSession);
|
||||
_logger.LogInformation("Session released for session ID: {SessionId}", mongoSession.SessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public Result<T> ExecuteInSession<T>(Func<IClientSessionHandle, Result<T>> action) {
|
||||
using var mongoSession = GetOrCreateSessionAsync().Result;
|
||||
|
||||
try {
|
||||
// Start the transaction
|
||||
mongoSession.Session.StartTransaction();
|
||||
|
||||
var result = action(mongoSession.Session);
|
||||
|
||||
if (!result.IsSuccess)
|
||||
// Abort the transaction if the action failed
|
||||
mongoSession.Session.AbortTransaction();
|
||||
|
||||
// Commit the transaction if the action was successful
|
||||
mongoSession.Session.CommitTransaction();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.LogError(ex, "Error during session operation.");
|
||||
return Result<T>.InternalServerError(default, "An error occurred during the operation.");
|
||||
}
|
||||
finally {
|
||||
ReleaseSession(mongoSession);
|
||||
_logger.LogInformation("Session released for session ID: {SessionId}", mongoSession.SessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<T>> ExecuteInSessionAsync<T>(Func<IClientSessionHandle, Task<Result<T>>> action) {
|
||||
using var mongoSession = await GetOrCreateSessionAsync();
|
||||
|
||||
try {
|
||||
// Start the transaction
|
||||
mongoSession.Session.StartTransaction();
|
||||
|
||||
// Execute the action within the session
|
||||
var result = await action(mongoSession.Session);
|
||||
|
||||
if (!result.IsSuccess)
|
||||
// Abort the transaction if the action failed
|
||||
await mongoSession.Session.AbortTransactionAsync();
|
||||
|
||||
// Commit the transaction if the action was successful
|
||||
await mongoSession.Session.CommitTransactionAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.LogError(ex, "Error during async session operation.");
|
||||
return Result<T>.InternalServerError(default, "An error occurred during the async operation.");
|
||||
}
|
||||
finally {
|
||||
ReleaseSession(mongoSession);
|
||||
_logger.LogInformation("Session released for session ID: {SessionId}", mongoSession.SessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
118
src/MaksIT.MongoDB.Linq/Utilities/CombGuidGenerator.cs
Normal file
118
src/MaksIT.MongoDB.Linq/Utilities/CombGuidGenerator.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
|
||||
namespace MaksIT.MongoDB.Linq.Utilities {
|
||||
public static class CombGuidGenerator {
|
||||
private const int TimestampByteLength = 6; // Number of bytes to store the timestamp
|
||||
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new COMB GUID by combining a randomly generated GUID with the current UTC timestamp.
|
||||
/// A COMB (COMBined) GUID includes both randomness and a timestamp for better sortability in databases.
|
||||
/// </summary>
|
||||
/// <returns>A new COMB GUID containing a random GUID and the current UTC timestamp.</returns>
|
||||
public static Guid CreateCombGuid() {
|
||||
return CreateCombGuidWithTimestamp(Guid.NewGuid(), DateTime.UtcNow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new COMB GUID by combining a specified GUID with the current UTC timestamp.
|
||||
/// This allows the caller to use a specific GUID while embedding the current time for better sortability.
|
||||
/// </summary>
|
||||
/// <param name="baseGuid">The base GUID to combine with the current UTC timestamp.</param>
|
||||
/// <returns>A new COMB GUID combining the provided GUID with the current UTC timestamp.</returns>
|
||||
public static Guid CreateCombGuid(Guid baseGuid) {
|
||||
return CreateCombGuidWithTimestamp(baseGuid, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new COMB GUID by combining a randomly generated GUID with a specified timestamp.
|
||||
/// Useful for creating GUIDs that incorporate a specific time, such as for historical data.
|
||||
/// </summary>
|
||||
/// <param name="timestamp">The timestamp to embed in the GUID.</param>
|
||||
/// <returns>A new COMB GUID combining a random GUID with the specified timestamp.</returns>
|
||||
public static Guid CreateCombGuid(DateTime timestamp) {
|
||||
return CreateCombGuidWithTimestamp(Guid.NewGuid(), timestamp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new COMB GUID by combining a specified GUID and timestamp.
|
||||
/// This method provides full control over both the GUID and timestamp components.
|
||||
/// </summary>
|
||||
/// <param name="baseGuid">The base GUID to combine with the provided timestamp.</param>
|
||||
/// <param name="timestamp">The timestamp to embed in the GUID.</param>
|
||||
/// <returns>A new COMB GUID combining the provided GUID and timestamp.</returns>
|
||||
public static Guid CreateCombGuidWithTimestamp(Guid baseGuid, DateTime timestamp) {
|
||||
Span<byte> guidBytes = stackalloc byte[16];
|
||||
baseGuid.TryWriteBytes(guidBytes);
|
||||
|
||||
// Write the timestamp into the last 6 bytes of the GUID
|
||||
Span<byte> timestampBytes = guidBytes.Slice(10, TimestampByteLength);
|
||||
WriteTimestampBytes(timestampBytes, timestamp);
|
||||
|
||||
return new Guid(guidBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the embedded timestamp from a COMB GUID.
|
||||
/// Allows retrieval of the timestamp component from a previously generated COMB GUID.
|
||||
/// </summary>
|
||||
/// <param name="combGuid">The COMB GUID from which to extract the timestamp.</param>
|
||||
/// <returns>The DateTime embedded in the provided COMB GUID.</returns>
|
||||
public static DateTime ExtractTimestamp(Guid combGuid) {
|
||||
Span<byte> guidBytes = stackalloc byte[16];
|
||||
combGuid.TryWriteBytes(guidBytes);
|
||||
|
||||
// Extract the timestamp bytes from the last 6 bytes of the GUID
|
||||
ReadOnlySpan<byte> timestampBytes = guidBytes.Slice(10, TimestampByteLength);
|
||||
return ReadTimestampFromBytes(timestampBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a DateTime to a series of bytes and writes it to the specified destination.
|
||||
/// Only the last 6 bytes of the Unix time in milliseconds are used to conserve space.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination span where the timestamp bytes will be written.</param>
|
||||
/// <param name="timestamp">The DateTime value to convert and write as bytes.</param>
|
||||
private static void WriteTimestampBytes(Span<byte> destination, DateTime timestamp) {
|
||||
long unixTimeMilliseconds = ConvertToUnixTimeMilliseconds(timestamp);
|
||||
Span<byte> unixTimeBytes = stackalloc byte[8];
|
||||
BinaryPrimitives.WriteInt64BigEndian(unixTimeBytes, unixTimeMilliseconds);
|
||||
unixTimeBytes.Slice(2, TimestampByteLength).CopyTo(destination); // Use only the last 6 bytes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads and converts a series of bytes back into a DateTime value.
|
||||
/// The source bytes represent the last 6 bytes of the Unix time in milliseconds.
|
||||
/// </summary>
|
||||
/// <param name="source">The source span containing the timestamp bytes to convert.</param>
|
||||
/// <returns>The DateTime value derived from the provided bytes.</returns>
|
||||
private static DateTime ReadTimestampFromBytes(ReadOnlySpan<byte> source) {
|
||||
Span<byte> unixTimeBytes = stackalloc byte[8];
|
||||
source.CopyTo(unixTimeBytes.Slice(2, TimestampByteLength)); // Copy the source to the last 6 bytes
|
||||
unixTimeBytes.Slice(0, 2).Clear(); // Zero the first 2 bytes
|
||||
long unixTimeMilliseconds = BinaryPrimitives.ReadInt64BigEndian(unixTimeBytes);
|
||||
return ConvertFromUnixTimeMilliseconds(unixTimeMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a DateTime to Unix time in milliseconds since the Unix epoch (January 1, 1970).
|
||||
/// This format is commonly used for storing and transmitting time as an integer.
|
||||
/// </summary>
|
||||
/// <param name="timestamp">The DateTime to convert to Unix time in milliseconds.</param>
|
||||
/// <returns>The Unix time in milliseconds representing the given DateTime.</returns>
|
||||
private static long ConvertToUnixTimeMilliseconds(DateTime timestamp) {
|
||||
return (long)(timestamp.ToUniversalTime() - UnixEpoch).TotalMilliseconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Unix time in milliseconds to a DateTime object.
|
||||
/// Useful for interpreting integer time values as readable dates.
|
||||
/// </summary>
|
||||
/// <param name="milliseconds">The Unix time in milliseconds to convert.</param>
|
||||
/// <returns>A DateTime object representing the given Unix time in milliseconds.</returns>
|
||||
private static DateTime ConvertFromUnixTimeMilliseconds(long milliseconds) {
|
||||
return UnixEpoch.AddMilliseconds(milliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
7
src/Release-NuGetPackage.bat
Normal file
7
src/Release-NuGetPackage.bat
Normal file
@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
|
||||
REM Change directory to the location of the script
|
||||
cd /d %~dp0
|
||||
|
||||
REM Invoke the PowerShell script (Release-NuGetPackage.ps1) in the same directory
|
||||
powershell -ExecutionPolicy Bypass -File "%~dp0Release-NuGetPackage.ps1"
|
||||
46
src/Release-NuGetPackage.ps1
Normal file
46
src/Release-NuGetPackage.ps1
Normal file
@ -0,0 +1,46 @@
|
||||
# Retrieve the API key from the environment variable
|
||||
$apiKey = $env:NUGET_MAKS_IT
|
||||
if (-not $apiKey) {
|
||||
Write-Host "Error: API key not found in environment variable NUGET_MAKS_IT."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# NuGet source
|
||||
$nugetSource = "https://api.nuget.org/v3/index.json"
|
||||
|
||||
# Define paths
|
||||
$solutionDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$projectDir = "$solutionDir\PodmanClient"
|
||||
$outputDir = "$projectDir\bin\Release"
|
||||
|
||||
# Clean previous builds
|
||||
Write-Host "Cleaning previous builds..."
|
||||
dotnet clean $projectDir -c Release
|
||||
|
||||
# Build the project
|
||||
Write-Host "Building the project..."
|
||||
dotnet build $projectDir -c Release
|
||||
|
||||
# Pack the NuGet package
|
||||
Write-Host "Packing the project..."
|
||||
dotnet pack $projectDir -c Release --no-build
|
||||
|
||||
# Look for the .nupkg file
|
||||
$packageFile = Get-ChildItem -Path $outputDir -Filter "*.nupkg" -Recurse | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
||||
|
||||
if ($packageFile) {
|
||||
Write-Host "Package created successfully: $($packageFile.FullName)"
|
||||
|
||||
# Push the package to NuGet
|
||||
Write-Host "Pushing the package to NuGet..."
|
||||
dotnet nuget push $packageFile.FullName -k $apiKey -s $nugetSource --skip-duplicate
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "Package pushed successfully."
|
||||
} else {
|
||||
Write-Host "Failed to push the package."
|
||||
}
|
||||
} else {
|
||||
Write-Host "Package creation failed. No .nupkg file found."
|
||||
exit 1
|
||||
}
|
||||
49
src/Release-NuGetPackage.sh
Normal file
49
src/Release-NuGetPackage.sh
Normal file
@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Retrieve the API key from the environment variable
|
||||
apiKey=$NUGET_MAKS_IT
|
||||
if [ -z "$apiKey" ]; then
|
||||
echo "Error: API key not found in environment variable NUGET_MAKS_IT."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NuGet source
|
||||
nugetSource="https://api.nuget.org/v3/index.json"
|
||||
|
||||
# Define paths
|
||||
scriptDir=$(dirname "$0")
|
||||
solutionDir=$(realpath "$scriptDir")
|
||||
projectDir="$solutionDir/PodmanClient"
|
||||
outputDir="$projectDir/bin/Release"
|
||||
|
||||
# Clean previous builds
|
||||
echo "Cleaning previous builds..."
|
||||
dotnet clean "$projectDir" -c Release
|
||||
|
||||
# Build the project
|
||||
echo "Building the project..."
|
||||
dotnet build "$projectDir" -c Release
|
||||
|
||||
# Pack the NuGet package
|
||||
echo "Packing the project..."
|
||||
dotnet pack "$projectDir" -c Release --no-build
|
||||
|
||||
# Look for the .nupkg file
|
||||
packageFile=$(find "$outputDir" -name "*.nupkg" -print0 | xargs -0 ls -t | head -n 1)
|
||||
|
||||
if [ -n "$packageFile" ]; then
|
||||
echo "Package created successfully: $packageFile"
|
||||
|
||||
# Push the package to NuGet
|
||||
echo "Pushing the package to NuGet..."
|
||||
dotnet nuget push "$packageFile" -k "$apiKey" -s "$nugetSource" --skip-duplicate
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Package pushed successfully."
|
||||
else
|
||||
echo "Failed to push the package."
|
||||
fi
|
||||
else
|
||||
echo "Package creation failed. No .nupkg file found."
|
||||
exit 1
|
||||
fi
|
||||
Loading…
Reference in New Issue
Block a user