azure-cosmos-dotnet-repository

Wraps the .NET SDK for Azure Cosmos DB abstracting away the complexity, exposing a simple CRUD-based repository pattern

MIT License

Stars
297
Committers
29

Bot releases are hidden (Show)

azure-cosmos-dotnet-repository - Release 3.5.1

Published by mumby0168 over 2 years ago

azure-cosmos-dotnet-repository - Release 3.5.0

Published by mumby0168 over 2 years ago

What's Changed

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/3.4.1...3.5.0

azure-cosmos-dotnet-repository - Release 3.4.1

Published by mumby0168 over 2 years ago

azure-cosmos-dotnet-repository - Release 3.4.0

Published by mumby0168 over 2 years ago

What's Changed

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/3.3.0...3.4.0

azure-cosmos-dotnet-repository - Release 3.3.0

Published by mumby0168 over 2 years ago

azure-cosmos-dotnet-repository - Release 3.2.0

Published by mumby0168 over 2 years ago

azure-cosmos-dotnet-repository - Release 3.1.0

Published by mumby0168 over 2 years ago

azure-cosmos-dotnet-repository - Release 3.0.3

Published by mumby0168 over 2 years ago

What's Changed

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/3.0.2...3.0.3

azure-cosmos-dotnet-repository - Release 3.0.2

Published by mumby0168 over 2 years ago

azure-cosmos-dotnet-repository - Release 3.0.0

Published by mumby0168 over 2 years ago

Breaking Changes v3.0.0

Nullable Reference Types

The most significant change to the library is the support for nullable reference types. The API surface has been updated to fully support null reference types. This may introduce warnings to code that previously may not have had to be null aware. This will introduce compile errors in projects that have <TreatWarningsAsErrors>True</TreatWarningsAsErrors> in a projects .csproj file.

GetAsync method.

The _repository.GetAsync(id, partitionKey) method was used to previously have a scenario where the API would return null.

This case was when the library read an item from cosmos successfully but the type field did not match that of the name of the class used. i.e. take the example below.

{
    "partitionKey": "BookCategory",
    "_etag": "\"3100b48c-0000-0700-0000-6219f58b0000\"",
    "timeToLive": null,
    "createdTimeUtc": "2022-02-26T09:40:27.000061Z",
    "id": "Engineering",
    "type": "BookCategory", // <--------- TYPE Field
    "_rid": "vG1RAMQtoX4LAAAAAAAAAA==",
    "_self": "dbs/vG1RAA==/colls/vG1RAMQtoX4=/docs/vG1RAMQtoX4LAAAAAAAAAA==/",
    "_attachments": "attachments/",
    "_ts": 1645868427
}

Notice the type field's value is BookCategory if I was to use a repository let's say with a class called Category the repository that you'd use via DI would look like IRepository<Category> when you made a read for this item the value of the type field from the above JSON does not match the name of the class. This would not previously result in an exception but return null to the caller.

📣 The library now in this case throws an exception instead of returning null. The exception that will be thrown in the MissMatchedTypeDiscriminatorException code the previously checked for null will now have to catch this exception.

Opt-in to receive total item counts when paging.

Previously when using either of the paging operations provided by this library it would run a count query for every page request. This, however, can incur a large RU charge for large data sets. For this reason, we have chosen to make this now an opt-in feature. When calling either of the paging methods you will need to pass a bool to indicate you would like the count query to be run. See an example below.

_dogRepository.PageAsync(
    d => d.Breed == "cocker spaniel", 
    pageNumber, 
    pageSize,
    returnTotal: true);

this returnTotal field defaults to false.

ETagItem is now abstract

This is a small change that makes the ETagItem class abstract.

What's Changed

New Contributors

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.12.1...3.0.0

azure-cosmos-dotnet-repository - Release 2.12.1

Published by mumby0168 over 2 years ago

azure-cosmos-dotnet-repository - Release 2.12.0

Published by mumby0168 over 2 years ago

What's Changed

New Contributors

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.11.0...2.12.0

azure-cosmos-dotnet-repository - Release 2.12.0-pre1

Published by mumby0168 over 2 years ago

What's Changed

New Contributors

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.11.0...2.12.0-pre1

azure-cosmos-dotnet-repository - Release 2.11.0

Published by mumby0168 almost 3 years ago

What's Changed

New Contributors

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.10.1...2.11.0

azure-cosmos-dotnet-repository - Release 2.10.1

Published by mumby0168 almost 3 years ago

What's Changed

New Contributors

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.10.0...2.10.1

azure-cosmos-dotnet-repository - Release 2.10.0

Published by mumby0168 almost 3 years ago

What's Changed

New Contributors

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.9.0...2.10.0

azure-cosmos-dotnet-repository - Release 2.9.0

Published by mumby0168 almost 3 years ago

Release 2.9.0

What's Changed

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.8.0...2.9.0

See the optimistic concurrency control sample for an example of how to use etags.

async Task ConcurrencyWithOptimizeBandwidthOff()
{
    Console.WriteLine($"Optimized bandwidth OFF.");
    IRepository<BankAccount> repository = BuildRepository(false);

    BankAccount currentBankAccount = await repository.CreateAsync(new BankAccount()
    {
        Name = "Current Account",
        Balance = 500.0,
        TimeToLive = TimeSpan.FromHours(4)
    });

    Console.WriteLine($"Created a bank account: {currentBankAccount}.");

    currentBankAccount.Withdraw(500);
    await repository.UpdateAsync(currentBankAccount);
    currentBankAccount.Deposit(500);

    Console.WriteLine($"Simulating a withdrawal of 500 that happened from another service. Remote State - {await repository.GetAsync(currentBankAccount.Id)}. Local State - {currentBankAccount}");

    Console.WriteLine("Attempting to withdraw 250 from the bank account.");
    try
    {
        Console.WriteLine("Attempting to withdraw 250 from the bank account.");
        await repository.UpdateAsync(currentBankAccount.Id,
            builder => builder.Replace(account => account.Balance, currentBankAccount.Balance - 250), etag: currentBankAccount.Etag);
    }
    catch (CosmosException exception) when (exception.StatusCode == HttpStatusCode.PreconditionFailed)
    {
        Console.WriteLine("Failed to withdraw 250 from the bank account as the local state was out of date with the remote state.");
        Console.WriteLine("Syncing local state with remote state.");
        currentBankAccount = await repository.GetAsync(currentBankAccount.Id);
        Console.WriteLine($"Updated local state. {currentBankAccount}");
    }

    try
    {
        Console.WriteLine("Attempting to withdraw 750 from the bank account.");
        currentBankAccount.Withdraw(750);
        currentBankAccount = await repository.UpdateAsync(currentBankAccount);
    }
    catch (InvalidOperationException)
    {
        Console.WriteLine("Failed to withdraw 750 from the bank account as it would take the user overdrawn.");
    }

    currentBankAccount.Deposit(500);
    await repository.UpdateAsync(currentBankAccount);
    currentBankAccount.Withdraw(500);

    Console.WriteLine($"Simulating a deposit of 500 that happened from another service. Remote State - {await repository.GetAsync(currentBankAccount.Id)}. Local State - {currentBankAccount}");

    Console.WriteLine("Forcing the balance to equal 1000");
    currentBankAccount.Balance = 1000.0;
    currentBankAccount = await repository.UpdateAsync(currentBankAccount, ignoreEtag: true);

    Console.WriteLine($"Forced update succeeded as etag was ignored.  Remote State - {await repository.GetAsync(currentBankAccount.Id)}. Local State - {currentBankAccount}");
}

Big thanks to @robertbennett1998 a lot of hard work has gone into this release 🥳

azure-cosmos-dotnet-repository - Release 2.8.0

Published by mumby0168 almost 3 years ago

What's Changed

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.7.1...2.8.0

See the samples for paging support

async Task BasicScrollingAsync()
{
    double totalCharge = 0;

    IPage<Person> page = await repository.PageAsync(pageSize: 25);

    foreach (Person person in page.Items)
    {
        Console.WriteLine(person);
    }

    totalCharge += page.Charge;

    Console.WriteLine($"First 25 results cost {page.Charge}");

    page = await repository.PageAsync(pageSize: 25, continuationToken: page.Continuation);

    foreach (Person person in page.Items)
    {
        Console.WriteLine(person);
    }

    totalCharge += page.Charge;
    Console.WriteLine($"Second 25 results cost {page.Charge}");

    page = await repository.PageAsync(pageSize: 50, continuationToken: page.Continuation);

    foreach (Person person in page.Items)
    {
        Console.WriteLine(person);
    }

    totalCharge += page.Charge;

    Console.WriteLine($"Last 50 results cost {page.Charge}");
    Console.WriteLine($"Total Charge {totalCharge} RU's");
}

Big thanks to Shay & Andriy from the EF core team who offered a lot of support on this one 👍 and as always to @IEvangelist 🥳

azure-cosmos-dotnet-repository - Release 2.7.1

Published by mumby0168 almost 3 years ago

What's Changed

New Contributors

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.7.0...2.7.1

azure-cosmos-dotnet-repository - Release 2.7.0

Published by mumby0168 almost 3 years ago

What's Changed

Full Changelog: https://github.com/IEvangelist/azure-cosmos-dotnet-repository/compare/2.6.0...2.7.0

Partial Updates Code Samples

[HttpPut("{id}")]
public async ValueTask<IActionResult> UpdateName([FromRoute] string id, [FromQuery] string name)
{
    if (string.IsNullOrWhiteSpace(name))
    {
        return BadRequest("A name is required");
    }

    await _repository
        .UpdateAsync(id: id,
            builder: builder => builder.Replace(language => language.Name, name));

    return Ok();
}
await _dogRepository.UpdateAsync(dog.Id, builder => builder.Replace(d => d.Name, "kenny"), dog.Breed);