-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Add support for CosmosDB #166
Comments
The one thing I'm unsure about is how to handle the
|
It depends on whether the concept of navigation properties (both entities and collections) exists in Cosmos DB. If it does not then I would throw the exception. If it does exist then how is it represented as a LINQ query i.e. do what you would do manually. Maybe it would help to observe the existing code with regard to select and expand, and what happens when none, all or a partial set have been specified. |
In this case there is no concept of a navigation property in Cosmos DB. You can have collections (primitives or objects) but they're not navigation properties. Nothing officially connects one document to another. You can of course embed an ID of one document into another:
But you cannot "join" those documents together (either with the C# SDK or Cosmos DB SQL API). E.g., First: |
|
Just doing manual testing at the moment, everything looks good. I know that the following are supported:
I don't believe transformations are currently supported, e.g., Maybe after this PR I'll look into adding transformations, but it'll probably require creating a dynamic runtime type (which I believe I could use this for). Also, returning an |
I believe that's all for options. FYI - there's a discussion here about configuring the |
Some dedicated classes may be worth considering for transforms. There are scenarios e.g. iOS Xamarin/Maui where anonymous types won't work. |
It looks as if I've found a bit of a bug in how we handle expansions. Currently in order to expand a complex type the following syntax is used I know we're assuming the following expansion syntax: This may be a specific CosmosDB concern as I don't believe a collection of complex types makes sense for a relational DB. |
Ok, so it looks like everything is working as expected (at least when tested manually). For other projects I've used Testcontainers to spin up a docker image running the Cosmos DB emulator. I was thinking of doing the same here for integration testing. Thoughts? |
Don't think I've used one. The only restriction is that anyone should be able to clone the repository build and test. The tests e.g. AutoMapper.OData.EF6.Tests should also work in the CI and release builds - not the web tests we switch those off. BTW adding this Cosmos DB piece to your repo for your own NuGet library is also an option - adding it here is great too. |
Using Docker containers (using the Originally I was planning on adding the feature here but if you'd feel more comfortable with me creating a separate Nuget package I can do that as well. |
I'm not familiar with the technology so whatever works with the CI. The expression builder tests check a string representation of the expression (in this case Cosmos DB looks like a good fit with the other two libraries. I brought up your own NuGet because of the whole dynamic: my lack of knowledge of Cosmos DB, your work etc.. in case you hadn't thought of it. |
So, it looks like the The issue, which may be a deal breaker, would be the requirement for the user to have docker installed on their machine in order to run the Cosmos DB tests. I'm also looking into how I could potentially create a default The problems here is I wouldn't be able to test the The other issue would be when using |
Do you need For integration testing just whatever makes sense to you - maybe add a web project |
During testing I've run into a bit of a snag with the following method defined in the Currently the method is written as follows:
The issue is with this line: In order for this to work 100% correctly I'd need the following:
This includes collections of literal or complex types. Is that acceptable to you? Or would you prefer a PR to the |
Ok to move the code for now at least. Then complex types are not considered expansions? If they are then maybe the solution is to handle You'd mentioned we weren't handling complex types correctly - so may have to move it permanently anyway (or just fix expansions for complex types). I don't think the |
No, you can't The link you showed is for navigation properties nested in complex types. This does expand the For example:
Issuing the following query: Would throw an exception (only navigation properties can be expanded). The solution to that problem is to always "include" the complex type, which means creating a Of course, you could imagine folks having complex types with deeper nesting than what I've shown. I'm looking at the recursive algorithm that's used for creating the |
Yep I think you're correct the expansions (entities plus complex properties) should be determined in this step before the lambda expressions get built. |
@BlaiseD Yeah that was exactly what I was thinking as well. It took a few days, but it looks like the algorithm for "including" the complex types is working correctly. One issue (which I don't think I'd tackle for this PR and might actually require changes to |
So I'm getting there but this PR is going to be fairly large. It's difficult making smaller PR's when using the git flow though.. I guess when it finally comes time to actually create the PR you'll have to make the decision whether you feel comfortable accepting such a large PR. Most of the changes are contained within the new This was problematic as that didn't allow for value collection filtering with the Furthermore I had to make changes to the |
Should be fine if most of the PR is new code - best to minimize the changes to existing logic. |
So there appears to be an issue with how we handle sub filters on Take the following Edm Model:
With this filter: Currently we're not casting the We do have some tests which are testing the built expression to ensure we're comparing the Right now what I've done is change the generated expression to insert a |
Correct - at the root we still use |
I see the following logic in if (conversionType.IsEnum)
{
if (!(sourceNode is ConstantNode enumSourceNode))
{
if (GetClrType(sourceNode.TypeReference) == typeof(string))
return new ConstantOperator(null);
throw new ArgumentException("Expected ConstantNode for enum source node.");
}
return new ConvertToEnumOperator
(
GetConstantNodeValue(enumSourceNode, conversionType),
conversionType
);
} |
Yeah that was one of the first things I saw so I put a break point in there last night and it never hit. That piece of code you showed would only get hit if the user is manually casting:
What I've tentatively done is create a new type implementing the Ideally the convert node would be added while we're building the tree of course but this is a more complicated task. |
Yes. It should be inserted wherever it's recognized as a |
I'm assuming the following was deleted by you? "I wonder if it's a bug in the OData parser as it never gets recognized as a QueryNode". I don't see it in the thread. The reference should be here. Then special handling for enums within that code. Also, the OData repository could be helpful if it works at the root level. |
Yeah I deleted those because I misunderstood the question initially. |
This is a bit of an interesting problem.
We're taking a There isn't a way to convert an So, in the case of a Or, I could build a more complicated
|
Doubt you need a new [Fact]
public void EnumInExpression_NullableEnum_WithNullable_IntegerList()
{
//act
var filter = CreateFilter<DataTypes>();
var constant = (ConstantExpression)((MethodCallExpression)filter.Body).Arguments[0];
var values = (IList<int?>)constant.Value;
//assert
AssertFilterStringIsCorrect(filter, "$it => System.Collections.Generic.List`1[System.Nullable`1[System.Int32]].Contains(Convert($it.NullableSimpleEnumProp))");
Assert.Equal(new int?[] { 1, 2 }, values);
Expression<Func<T, bool>> CreateFilter<T>()
=> GetFilter<T>
(
new InOperator
(
new ConvertOperator
(
new MemberSelectorOperator("NullableSimpleEnumProp", new ParameterOperator(parameters, parameterName)),
typeof(int?)
),
new CollectionConstantOperator(new List<object> { 1, 2 }, typeof(int?))
),
parameters
);
} The cast should probably come from the request. In the worst case the |
By default I'm casting all Same with this: If a cast was requested nothing is changed, so this: Actually, the test you should is essentially what I changed in the Just tested this and it works well, thank-you. |
I'm a bit confused by the ConvertToStringOperator. If the user specified So, if the user was storing their Query Expected Expression Or am I not understanding something? I believe the
|
After any changes, the functionality should more closely mirror the OData repo rather than stray from it. I'm quite sure the SQL Server provider has trouble translating - among other things - I think, you're correct - we may want to submit a separate PR for changes to the existing code before the new stuff. |
Now, in the issue you linked to I think the issue was with using Currently in order to support The The reason behind the location was attempting to convert the Do you want me to make the changes to the |
OK what I'm going to do is create two new issues (for tracking purposes). The first issue will be adding support for the |
@BlaiseD So I was thinking of submitting a WIP PR for this feature. This would allow you to get some insight in to what I've been doing over the last couple months and will allow you to ask questions or raise some concerns you may have. I'm still in progress with this feature but for the most part it's fully functional. One thing I'm still on the fence about is how to handle queries such as Regardless, I just wanted to get a WIP PR in so that you could see what's happening. |
Regarding unsupported features I would look at what ASP.NET Odata does - not sure if there's any special handling. For WIP - better to submit a PR for the shared/existing classes first then a second one for the remaining Cosmos DB specific code. |
@BlaiseD So I haven't made any significant changes to any existing code. The changes that were made are just some minor extension methods added to I tried to keep everything as self contained as possible without code duplication. |
It would be nice to have support for working directly with the Cosmos DB LINQ provider as opposed to working with the EF provider as EF does not generate valid SQL in many situations.
The text was updated successfully, but these errors were encountered: