Coder Social home page Coder Social logo

ievangelist / azure-cosmos-dotnet-repository Goto Github PK

View Code? Open in Web Editor NEW
297.0 12.0 86.0 14.98 MB

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

Home Page: https://ievangelist.github.io/azure-cosmos-dotnet-repository

License: MIT License

C# 100.00%
azure-cosmos-db sdk crud repository-pattern dotnet hacktoberfest

azure-cosmos-dotnet-repository's Introduction

azure-cosmos-dotnet-repository's People

Contributors

afacanerman avatar allcontributors[bot] avatar beigebadger avatar boylec avatar danielmarbach avatar daveabrock avatar dcuccia avatar dependabot[bot] avatar emrekara37 avatar evancjohnson avatar fffffatah avatar filipmhpersson avatar github-actions[bot] avatar idormenco avatar ievangelist avatar imgbot[bot] avatar invvard avatar joelsteventurner avatar kevin-benton avatar manuelsidler avatar mo2k4 avatar mrfootoyou avatar mumby0168 avatar philip-reed avatar rabosa616 avatar richmercer avatar robennett2 avatar stormbringer766 avatar verycautious avatar westdiscgolf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-cosmos-dotnet-repository's Issues

Created & updated time stamps

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like

  • When a document is created mark the current time as DateTime.UtcNow
  • When a document is modified mark the last updated time as DateTime.UtcNow

Describe alternatives you've considered
This can be controlled manually by a user but it may be a nice addition for this library to handle.

Additional context
This is what the Item class could look like

    public abstract class Item : IItem
    {        
        [JsonProperty("id")]
        public string Id { get; set; } = Guid.NewGuid().ToString();

        [JsonProperty("type")]
        public string Type { get; set; }

        string IItem.PartitionKey => GetPartitionKeyValue();

        public Item() => Type = GetType().Name;

        protected virtual string GetPartitionKeyValue() => Id;
        
        [JsonProperty("createdUtc")]
        public DateTime CreatedUtc { get; internal set; }

        [JsonProperty("lastUpdatedUtc")]
        public DateTime LastUpdatedUtc { get; internal set; }
    }

Not getting data from local Cosmos Db

First I am probably biting off more than I can chew. I have a fair amount of experience but all pretty simple apps in the past. Having said that, I stumbled on the package and cloned the repository. I looked at the Azure Function example specifically, since that is what I'm needing right now. My example that I was having trouble with redid the Startup, modified the data models to have the class from Item. installed the nugget package. Thought I am golden. The function compiles, throws no errors, looks in the cmd window that it succeeded, but returns a null from the GetAsync, the OkObjectResult shows a null. Anyway, I then tried to run the AzureFunctionTier on the solution cloned after making it work for my local Cosmos db. Can you point me in a direction of what in the world I could be doing wrong? This all looks dirt simple.

IItem default implementation?

Very cool abstraction, thank you! This is more of a "discussion," but just curious since it's so lightweight, whether you think a C# 8 "IItem" default interface implementation would suffice as a substitute for the concrete Item class. The use case here would be to support an existing model class hierarchy and hang these "traits" off that implementation. Id and Type currently require a backing field, which I'm not sure how to best accomplish this in that case. Just a thought! :)

Community chatroom

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like
A chatroom for the community, Discord would be my suggestion, no reason we can't have more than one?

Describe alternatives you've considered
n/a

Additional context
n/a

New class Attribute to customize container for item

Is your feature request related to a problem? Please describe.
I want to put some items in one container, but seems current setting only allows one item one container

Describe the solution you'd like
An attribute like partitionkey attribute on class should be good

Describe alternatives you've considered
no alternative I think

Additional context
none

Alternate method to configure container-name/partition-key for an item type

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like
Another way to configure the container name & partition key for a given item type this could be done when configuring the cosmos repository options or another extension method to services. Maybe something like below:

services.AddCosmosRepository().AddItem<Person>("people", "/email");

This may be better to be done as part of a configure action for this library such as:

services.AddCosmosRepository(configure => 
{
    configure.ConfigureRepository<Person>("people", "/email");
}

Describe alternatives you've considered
The alternate is already in place currently using the attributes.

Additional context
This could reduce the need for reflection using the attribute based approach if this option is used.

Set TTL (Time to live) at Item Level

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like
A way to configure a TimeSpan or seconds for an item to live for after it has been created.

Describe alternatives you've considered
Manually setting this as a the ttl property on a class that already implements Item or IItem

Additional context
n/a

Share throughput over containers

Is your feature request related to a problem? Please describe.
If ContainerPerItemType = true, the containers are created with their own throughput (autoscale or manual). However, I would like to share the total database throughput over the containers. This is a setting in Cosmos, but I can't get it to work.

Describe the solution you'd like
Add a setting, or make it possible to use manually created containers (see below).

Describe alternatives you've considered
I've tried to manually create the containers in the Data Explorer, and use those as Cosmos repositories, but this doesn't work.

Additional context
Thanks for this great library๐Ÿ™Œ

Implement CountAsync<TItem>

I would like to request a count of records for a given filter criteria/query. For example:
SELECT VALUE COUNT(1) FROM c WHERE c....

When querying CosmosDb directly, this returns a response as follows:

[
    27
]

(In the example above, there are 27 records)

Using the repository, this doesn't seem possible. Is there a way to use the existing repository to get the above result back, or would a new method be required?

Since all POCOs must derive from IItem, I have tried to create a POCO for the anonymous array response type above but have faced some challenges (with deserialization, etc). I don't this its possible (but could be wrong, only spent a few minutes experimenting).

Feature request: pagination support

When we get items from repo, if the count of items is more than several thousands, a better way is to get data by page, can we support it?

Unique-Key constraint configurable

There is not jet a possibility to create containers with a unique-key-constraint.

Because of that it would be great if one could specify those. Maybe one could add an attribute to the Property that should be unique, int the Item that implaments the IItem interface.

Then when a container is created, the type it is created for is checked for this attribute.

Support Pre-Release Nuget Packages

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like
In order to let consumers move with some newer features that may include breaking changes allow a pre-release version be published including newer features.

Implement ExistsAsync<TItem>

A set of overloads to see if an instance of a TItem exists.

The api should allow for a simple point read to see if an item exists ValueTask<boo> ExistsAsync(string id, string pk = null)

It can also include a implementation that allows a Expression<TItem> to be used.

Transforming the model in a GET response

I would like to return a different model (POCO class that derives from Item) on some GET responses/read operations for a given repository.

This model would be a cut down version of the "main" model and only return the fields specified in the query that is sent to CosmosDb.

Let's say we have a "Person" entity and, instead of returning the full JSON payload for an entire person, the SQL query provided to CosmosDb would contain a subset of the fields. For example: "SELECT c.firstName, c.lastName, c.dob, c.status FROM c WHERE c....". (so here we are only returning 4 fields).

Unless I am missing something, it seems that, at the moment, because the repositories are typed to a single model, one can only retrieve that one full entity and can't get CosmosDb onto retrieve a subset if the fields for the entity.

For large documents this could be an issue brining all the data for an entity across the wire to the calling Web API needlessly only to be discarded by the API before sending to the client (API consumer). It could also be an issue for sensitive data.

Is the only way to get around this for now to create multiple [additional] repositories (one for each subset of response fields) for the same container/entity in Cosmos Db?

Feature : Managed identity

Thanks for the project!!
We want to access our database through managed Identity, when will it be possible ?

Set TTL (Time to Live) at Container Level

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like
A way to specify the default time to live for a whole container. This can be achieved via the code below. It would be a good feature to have this configurable for each container

CosmosClient cosmosClient = new CosmosClient("<conn-string>");
Database database = cosmosClient.GetDatabase("<database-id>");
await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
    DefaultTimeToLive = TimeSpan.FromDays(5).Seconds
});

Describe alternatives you've considered
n/a

Additional context
n/a

PropertyNamingPolicy doesn't work on Insert and Update

My SerilizationOptions setting is showed below.

            options.SerializationOptions = new Microsoft.Azure.CosmosRepository.Options.RepositorySerializationOptions
            {
                IgnoreNullValues = true,
                PropertyNamingPolicy = Microsoft.Azure.Cosmos.CosmosPropertyNamingPolicy.Default,
                Indented = true,
            };

I can sucessfully select values but when I try to update or insert new ones, they are updated in Cosmos db with CamelCase naming settings.

I cannot select these newly inserted values too because of My NamingPolicy is "Default".

I even tried to use JsonProperty but it didn't worked either.

image
image

Issue loading Microsoft.Extensions.DependencyInjection.Abstractions

I'm not sure if this is a problem with my machine or not, but wanted to ask.

When I try to run my Azure Function after bringing in and using your awesome library, I get a runtime error:

[2020-11-27T15:01:03.561Z] Api: Could not load file or assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
Value cannot be null. (Parameter 'provider')

I've tried to mirror your sample, so my project file looks almost the same as yours. Here's the most important bits:

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
  </PropertyGroup>
...
<ItemGroup>
    <PackageReference Include="IEvangelist.Azure.CosmosRepository" Version="2.1.1" />
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.10" />
</ItemGroup>

The difference is that I fetched your project in NuGet, and in your sample you're using a project reference. When I look at dependencies in NuGet, I see it is supported in .NET Standard 2.0:

image

I'm using .NET Core 3.1, as you are, so that should be OK. Knowing the Microsoft.Azure.Cosmos dependency wasn't an issue, I explicitly referenced the Microsoft.Extensions.* dependencies in my project file but that didn't help.

I noticed a GitHub issue from a few weeks ago, noting a potential problem with the host version. Are these 5.0.0 dependencies mucking things up?

Configurable RU's for Containers

When using the ContainerPerItemType setting it is possible that a consumer would want to be able to setup the container to have a set amount of RU's.

The library should be able to expose this configuration see this link for information on how the cosmos SDK exposes this.

https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.cosmos.database.createcontainerifnotexistsasync?view=azure-dotnet

We could add this on top of our ContainerBuilder for a specific item.

The basics options are defined as ThroughputProperties these can be set to auto scale or manual.

[Question] Assigning the PartitionKey

Hi

I am trying to use this package configuring the custom partition key (/userIdentifier) instead of /Id, but I am getting an error from cosmos client as below
System.ArgumentException: The requested partition key path '/id' does not match existing Container 'VideoElapsedTimeData' with partition key path '/userIdentifier' (Parameter 'PartitionKey')

public class VideoElapsedTimeData : Item
    {
        [JsonProperty("userIdentifier")] public string UserIdentifier { get; set; }
        [JsonProperty("consumedTimeInMs")] public double ConsumedTimeInMs { get; set; }
        [JsonProperty("metadata")] public string Metadata { get; set; } = string.Empty;
        [JsonProperty("videoType")] public string VideoType { get; set; } = string.Empty;
        [JsonProperty("viewedPercentage")] public double ViewedPercentage { get; set; }
        [JsonProperty("trimInMs")] public double TrimInMs { get; set; }
        [JsonProperty("trimOutMs")] public double TrimOutMs { get; set; }
        [JsonProperty("timestamp")] public DateTimeOffset Timestamp { get; set; } = DateTimeOffset.UtcNow;

        [JsonProperty("videoId")] public string VideoId { get; set; }

        protected override string GetPartitionKeyValue() => UserIdentifier;
    }

My container partition key set as /userIdentifier

image

Probably I am missing something I would be so glad if you could help, please.

Thank you

Filtering by type seems broken

The type filtering within the GetAsync method seems broken when configured to use a single container with different types differentiated by the "Type" field.

This is obviously a critical issue because if someone saves a "Person", then attempts to load and save a "Car", the bug causes this package to deserializes a Person into the Car object, and once saved back into Cosmos will delete all the Person fields. This is critical as it will lead to corruption and loss of data if this package is used in production.

Taking a quick look, I can see that part of the code handling this inside GetAsync has changed a lot over the last 6-months. As a temporary work around you can include the filtering inside your own predicate, such as i => i.Type == nameof(MyType) && ....

But obviously the whole point of this package is to do that for you and guarantee it (which appears dangerously broken). If I get a chance I will look at a fix. We probably need a test case to make sure this does not regress again given how critical it is.

Also note that people will not notice this if:
a) They are using separate containers.
or
b) They are only using this package to store a single type in their project.

In memory running option

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like
It would be useful to have a implementation of the IRepository<T> which would run an in memory store much like what EF core provides. Matching the cosmos API wherever possible for use alongside the Microsoft.AspNetCore.Mvc.Testing nuget package. This would be great for running integration tests in pipelines.

Describe alternatives you've considered
Running test's against a real version of cosmos locally or in Azure.

Additional context
n/a

You're required to use version 2.14 for Azure Functions

Original title: Upgrade to C# 9.0 breaks azure functions

I am not sure if you are aware of this, and I don't consider it a bug but maybe it will save some other people some time. Versions of this library that target C# 9 (after 2.14) break azure functions with aspnetcore 3.1. The Azure Functions sample in this repository doesn't work anymore.

I won't be upgrading my function apps until .NET 6 is released so for now I will stick with 2.14.

Creating a container with a different class

I have defined a class and I am inserting an item in the container with another class (which inherits from it).

image

But the container is creating from the class I passed, not from the class I defined in the repository.

image

Bulk Update

Currently only bulk create is supported by the package, where an IEnumerable can be passed to CreateAsync function and items are added to the cosmos container. This functionality is missing for UpdateAsync. It comes in handy when you have multiple items that needs to be added and increases performance.

Add a new UpdateAsync function that accepts IEnumerable and updates the cosmos container values
UpdateAsync(IEnumerable values, CancellationToken cancellationToken = default);

I cloned the repo and added the function locally on my machine, tested and working as expected.

If this is a feature that you see valuable, I can create a PR for review.

Linq Queryable Decorator

Someone may know the answer to this but as we do not expose the LinqQueryable how would a consumer chain extra linq methods other than just a .Where(x => ...) clause, would we need to add some sort of extra API for this?

Container Syncing

The new configuration options that have been provided as part of this library may mean that containers become out of sync with what is configured within this library.

An opt-in option to sync container properties when the container is initially lazy-loaded can allow clients to keep their container settings in sync.

There should also be a manual option provided via a DI-enabled service to manually sync these containers if clients don't want to take the hit on the first request for that container.

Add a Managed Identity example

Is your feature request related to a problem? Please describe.
Support for authentication using Manage Identities was added in #114, but the documentation was note updated with any examples on how to use this. On the surface it would appear that you simply pass in a DefaultAzureCredential to the TokenCredential property, however this does not work out of the box for me.

Given a Startup.cs that looks like:

public override void Configure(IFunctionsHostBuilder builder)
{
    IConfigurationRoot config =
        new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();

    DefaultAzureCredential credential = new DefaultAzureCredential();

    builder.Services.AddCosmosRepository(options =>
    {
        options.CosmosConnectionString = config["Cosmos:ConnectionString"];
        options.DatabaseId = config["Cosmos:DatabaseId"];
        options.ContainerPerItemType = true;
        options.TokenCredential = credential;

        options.ContainerBuilder.Configure<DeviceTwinUpdate>(
            containerOptions =>
                containerOptions
                    .WithContainer("DeviceTwinUpdates")
                    // TODO: Configure Partition Key
        );

        options.ContainerBuilder.Configure<DeviceTelemetry>(
            containerOptions =>
                containerOptions
                    .WithContainer("DeviceTelemetry")
                    // TODO: Configure Partition Key
        );
    });
}

and a Function1.cs that looks like:

private readonly IRepository<DeviceTwinUpdate> _deviceTwinUpdateRepository;
private readonly IRepository<DeviceTelemetry> _deviceTelemetryRepository;

public Function1(IRepositoryFactory factory, CosmosClient cosmosClient)
{
    _deviceTwinUpdateRepository = factory.RepositoryOf<DeviceTwinUpdate>();
    _deviceTelemetryRepository = factory.RepositoryOf<DeviceTelemetry>();
}

[FunctionName("Function1")]
public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    try
    {
        var twin = await _deviceTwinUpdateRepository.GetAsync((a) => a.Id.Equals("321"));
        var telemetry = await _deviceTelemetryRepository.GetAsync((a) => a.Id.Equals("123"));
    }
    catch (Exception ex)
    {
        var t = "";
    }

    return new OkObjectResult("Success");
}

where both models directly inherits from Item

public class DeviceTwinUpdate : Item
{
}

public class DeviceTelemetry : Item
{
}

I expect to be able to retrieve data successfully.

However, I encounter the following error "Invalid URI: The URI scheme is not valid.", the stack trace is:

at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
at Microsoft.Azure.Cosmos.CosmosClient..ctor(String accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions)
at Microsoft.Azure.CosmosRepository.Providers.DefaultCosmosClientProvider.GetCosmoClient()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at System.Lazy`1.get_Value()
at Microsoft.Azure.CosmosRepository.Providers.DefaultCosmosClientProvider.UseClientAsync[T](Func`2 consume)
at Microsoft.Azure.CosmosRepository.Services.DefaultCosmosContainerService.GetContainerAsync[TItem](Boolean forceContainerSync)
at Microsoft.Azure.CosmosRepository.Providers.DefaultCosmosContainerProvider`1.<>c__DisplayClass1_0.<<-ctor>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---

I have isolated the error to be something with my DefaultAzureCredential that I pass to TokenCredential. I am running this inside Visual Studio 2019 which I am signed into with my Azure Account and this account is selected in the Azure Service Authentication section of my settings.

If I remove the setting of options.TokenCredential then my call succeeds. I have investigated the properties available for the DefaultAzureCredentialOptions parameter of DefaultAzureCredentials but none look particularly applicable or relevant for my use case.

Describe the solution you'd like
As outlined above there needs to be better guidance on how to use Managed Identities with this package.

Describe alternatives you've considered

  • I have managed to access data using the standard CosmosClient class from the C# SDK using a connection string.
  • I have also reviewed all of the samples in this repo and there is no example of using Managed Identity.
  • There is a guide here that outlines how to use Managed Identities with the standard library, but I'd much rather use this package as opposed to rolling my own.

Additional context
None

Last Updated Property on Item

Is your feature request related to a problem? Please describe.
n/a

Describe the solution you'd like
A property adding to the default Item type that includes the _ts (last-updated) timestamp provided by cosmos. This can be converted from unix time to a UTC value represented as a DateTime with the property name of LastUpdatedUtc.

Describe alternatives you've considered
Manually adding this property to items that already derive from Item

Additional context
n/a

GetAsync item.Type

More of a question, not sure if its an issue.
In DefaultRepository.GetAsync methods, there are mixed implementations for checking the Type property is set/defined on the Item.

return item is { Type: { Length: 0 } } || item.Type == typeof(TItem).Name ? item : default;

And

 IQueryable<TItem> query =
                container.GetItemLinqQueryable<TItem>()
                    .Where(predicate.Compose(
                        item => !item.Type.IsDefined() || item.Type == typeof(TItem).Name, Expression.AndAlso));

Are these doing the same thing?
The latter one seems to exclude items where Type is zero length string or null, am I reading that right?

Multiple containers support

Just a question:
Is it possible to support multiple containers (eg: one container for data, another container for audit) ?

Microsoft.Azure.Cosmos.ContainerProperties.set_UniqueKeyPolicy(UniqueKeyPolicy value) (version 2.1.8)

System.ArgumentNullException: Value cannot be null. (Parameter 'value')
at Microsoft.Azure.Cosmos.ContainerProperties.set_UniqueKeyPolicy(UniqueKeyPolicy value)
at Microsoft.Azure.CosmosRepository.Providers.DefaultCosmosContainerProvider1.GetContainerValueFactoryAsync() at Microsoft.Azure.CosmosRepository.Providers.DefaultCosmosContainerProvider1.<.ctor>b__7_0()
at Microsoft.Azure.CosmosRepository.DefaultRepository`1.GetAsync(String id, PartitionKey partitionKey, CancellationToken cancellationToken)
at Customer.Client.Controllers.PaymentController.Index() in D:\SourceGitHub\CustomerAPI\Customer.Client\Controllers\PaymentController.cs:line 22
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)

I am working on API project having Controller ->service layer-> Repository but getting the above error,
i have setup cosmosdb connection using overload in startup file (also tried using appsetting.development.json)
Still issue is not getting resolve
My model is as below:-
namespace Customer.Domain.Entities
{
[PartitionKeyPath("/dType")]
public class Payment : Item
{
public string uId { get; set; }
[JsonProperty("dType")]
public string dType { get;} = $"ap-payment";
public string accountUId { get; set; }
public string contractUId { get; set; }
public int billCycleNumber { get; set; }
public DateTime date { get; set; }
public string gclPaymentId { get; set; }
public string description { get; set; }
public string status { get; set; }
public string referenece { get; set; }
public DateTime createdOn { get; set; }
public DateTime updatedOn { get; set; }

    protected override string GetPartitionKeyValue() => dType;
}

}

Async methods CancellationToken

Please allow the developer can pass a CancellationToken to the Async methods; thus allowing timeout cancellations etc. for long running tasks

Why does CreateAsync return Task<IEnumerable<TItem>>?

https://github.com/IEvangelist/azure-cosmos-dotnet-repository/blob/main/Microsoft.Azure.CosmosRepository/src/IRepository.cs#L78

return Task<IEnumerable<TItem>> while

https://github.com/IEvangelist/azure-cosmos-dotnet-repository/blob/main/Microsoft.Azure.CosmosRepository/src/IRepository.cs#L64

returns ValueTask<IEnumerable<TItem>> any reasons why they are not alike?

Also, notice the xml doc is not up to date. Happy to send a PR if wanted. It seems though changing the interface return type is a breaking change so I wanted to ask first

Data loss with nuget package versions 2.1.4 through to 2.1.9

Sorry for being melodramatic, but this bug is critical enough and will definitely cause data loss in production. It is likely people will review this when trying to resolve.

Temporary resolution: Downgrade to nuget package version 2.1.3 until this issue has been resolved. I have verified version 2.1.3 has the correct behaviour.

With versions 2.1.4 through to 2.1.9, if you are storing multiple types within a single container in cosmos (which would be the default for most users), you will quickly corrupt your database. In summary, the codebase attempts to add an additional where clause to the predicate you supply to GetAsync, but the logic is not correct.

If you want a work around this bug and use more recent nuget package versions, you MUST include your own type filter within the predicate, for example if your type is MyName, you would have written this:

db.GetAsync(i => i.FirstName == "Fred")

If you use nuget package 2.1.4 to 2.1.9 you MUST include your own type filter in your supplied predicate like this:

db.GetAsync(i => i.FirstName == "Fred" && i.Type == nameof(MyType))

If you do not do this on later package version, you will end up corrupting your data.

Support for QueryDefinition

Hi,

GetByQueryAsync is accepting only string type query. This is open to the SQL injection attacks. Would it be ok to create another overload that accepts CosmosDB QueryDefinition?

ValueTask<IEnumerable<TItem>> GetByQueryAsync(QueryDefinition queryDefinition, CancellationToken cancellationToken = default);

I think this change would introduce CosmosDB package to the client but it would be safer.

I could create a PR if you want me to.

Ability to set CosmosClientOptions - helpful with local Docker Emulator usage

Is your feature request related to a problem? Please describe.
When attempting to use the repository in a containerised application the following error occurs:
"System.InvalidOperationException: Cannot create Collection Information for Drivers in database drivers with lease leases in database drivers : The SSL connection could not be established, see inner exception.
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception."

The lack of configurability is preventing me from using this really useful repository as part of our microservice solution

Describe the solution you'd like
Looking at this link it seems we can override certificate config, so the ability pass these options through (or the repo's own version of) would be a suggestion?
https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator?tabs=ssl-netstd21#disable-ssl-validation

CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
{
    HttpClientFactory = () =>
    {
        HttpMessageHandler httpMessageHandler = new HttpClientHandler()
        {
            ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
        };

        return new HttpClient(httpMessageHandler);
    },
    ConnectionMode = ConnectionMode.Gateway
};


CosmosClient client = new CosmosClient(endpoint, authKey, cosmosClientOptions);

Additional context
Unless there is currently a way of achieving local, containerised development already within the project I'm unaware of, I think solving this problem would open up the repository to another level of software.

Repository that does not depend on the Item class

image

I'm new to the world of Cosmos DB, but I was thinking: If I make a custom query, which involves several containers, shouldn't my repository be free? Not being forced to inherit a class that defines the container?

Smarter Container Syncing

There is currently a mechanism in the library that will allow you to sync container properties on the first request to an IRepository<TItem> for a given IItem type.

This currently will check the configured ContainerProperties by the library and then it will apply these to the cosmos container that the IItem is using. This does not take into account that IItems are sharing a container potentially applying these changes for every IItem when the first request is made to the container for the given IItem type.

This could be more intelligent and keep track of sync containers and if a request to one IItems repository has already been made which results in the container changes being sync then it skips this step.

The main issue with this is that the initial request takes time and reducing the times the ContainerProperties are synced for IItem types that share the same container will result in a performance increase.

Transactions and optimistic concurrency control

Hi I am working on a project that is using your library, the project requires that we handle some form of Transactions or optimistic concurrency control on the data. Essentially I need to read the data and change contents within the document and write it back.

What I want to avoid is when writing back to have a newer version in the database and my data ends up overwriting the current document.

Microsoft has already something that handles such situations (https://docs.microsoft.com/en-us/azure/cosmos-db/database-transactions-optimistic-concurrency#optimistic-concurrency-control) is this implemented within your library?

Selecting a partition key in an item class

This is an excellent package that makes it working with Cosmos DB a breeze. However, as there is a limit of 20GB per partition key and currently partitions defaulted per type, we cannot use this library on enterprise projects where data could be a lot bigger per partition.

Is it possible to select a partition key via JsonProperty so that the partition key can be specified within a repository item so that when ContainerPerItemType is set to true it can be used for larger data?

I am not sure if this is already implemented as it is not documented in the repository or blog post.

When to use Cosmos IRepository vs. EF Core DB Provider for Cosmos

Would love to understand reasons why/when one choose this IRepository API for Cosmos over the EF Core DB provider for Cosmos.

There's some overlap in functionality since EF Core's DbSet<T> is essentially like an IRepository<T>, right? Perhaps this answer might be worth adding to the readme or wiki, so it's not buried is this GH issue.

Explore source generators as an alternative to reflection-based attribute usage

Currently there are several attributes that are exposed to consumers:

  • PartitionKeyPath
  • Container

These attributes are used to declaratively serve as a means for specifying the partition key path of an item or the container an item should belong to respectively. It would be nice to avoid reflection-based attribute usage, and instead source generate the implementation details - but that might be a breaking change, as partial item classes might be required... nonetheless, explore it.

Exception when Item doesn't exist

We are continuously addressing and improving the SDK, if possible, make sure the problem persist in the latest SDK version.

I'm using this cool wrap along with mediataR, when I try to get an Item using GetAsync and it does not exist
I got this exception: Microsoft.Azure.Cosmos.CosmosException : Response status code does not indicate success: NotFound (404); Substatus: 0; ActivityId: 18f33e01-f625-4439-ab27-f2ff7f6be36b; Reason: ()

To Reproduce

        public async Task<GetUserResponse> Handle(GetUserRequest request, CancellationToken cancellationToken)
        { 
            var user = await _db.GetAsync(request.Id.ToString(), cancellationToken: cancellationToken);
            if (user is null)
            {
                throw new ArgumentException();
            } 
            return user.Adapt<GetUserResponse>();
        }

Expected behavior
GetAsync is supposed to be a null when not match the type

Actual behavior
Raising a exception

Environment summary
SDK Version: 2.3.0
OS Version (MacOSX)

Additional context
Add any other context about the problem here (for example, complete stack traces or logs).

Need feature to disable or override "type" property with other name

I already have a property in my class and cosmos Db named "type",
which causes the issue when retrieving an item as the type field is in CosmosDb and Repository Item so we have a conflict.

Could you please add a feature so we can disable the Item class's "type" property if not required? OR
If we can override/rename it with some other property name.

Also, can we use UnitOfWork with your current repository?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.