Skip to content
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

Update ODataTypeInfo.cs not correctly identifying entity keys by "Id" property #3050

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

lawynn
Copy link

@lawynn lawynn commented Aug 30, 2024

I found an issue where the Conventional Id fields are not recognized as key fields. As the Property Name Ends with Id, rather than "ID". The result is that the EdmModel is properly defining the key property, however on the client the EntityType is resolved as "ComplexType" and failures in tracking occur later on in the pipeline.

Issues

#3052

Description

This change finds Id properties using Case Insensitivity for cases where the [Key()] attribute is not defined.

Checklist (Uncheck if it is not completed)

  • Test cases added
  • Build and test with one-click build and test script passed

I found an issue where the Conventional Id fields are not recognized as key fields.  As the Property Name Ends with Id, rather than "ID".  The result is that the EdmModel is properly defining the key property, however on the client the EntityType is resolved as "ComplexType" and failures in tracking occur later on in the pipeline.
@lawynn
Copy link
Author

lawynn commented Aug 30, 2024

@lawynn please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree company="Microsoft"

@lawynn lawynn changed the title Update ODataTypeInfo.cs Update ODataTypeInfo.cs not correctly identifying entity keys by "Id" property Aug 30, 2024
xuzhg
xuzhg previously approved these changes Sep 19, 2024
xuzhg
xuzhg previously approved these changes Sep 19, 2024
Added unit tests for conventional keys
habbes
habbes previously approved these changes Sep 25, 2024
@habbes habbes self-requested a review September 25, 2024 03:53
@habbes
Copy link
Contributor

habbes commented Sep 25, 2024

The following test fails in the pipeline:

[xUnit.net 00:00:09.84]     Microsoft.OData.Client.Tests.ALinq.PreserveTypesAndAttributesTests.OneLevelOfInheritaceClassQuery_UsesRightPropertyNames_WhenCastedToBaseClass [FAIL]
  Failed Microsoft.OData.Client.Tests.ALinq.PreserveTypesAndAttributesTests.OneLevelOfInheritaceClassQuery_UsesRightPropertyNames_WhenCastedToBaseClass [3 ms]
  Error Message:
   System.NotSupportedException : Construction of entity type instances must use object initializer with default constructor.
  Stack Trace:
     at Microsoft.OData.Client.ProjectionAnalyzer.Analyze(LambdaExpression e, SelectExpandPathBuilder pb, DataServiceContext context) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ProjectionAnalyzer.cs:line 101
   at Microsoft.OData.Client.ProjectionAnalyzer.AnalyzeResourceExpression(LambdaExpression lambda, ResourceExpression resource, DataServiceContext context) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ProjectionAnalyzer.cs:line 233
   at Microsoft.OData.Client.ProjectionAnalyzer.Analyze(LambdaExpression le, ResourceExpression re, Boolean matchMembers, DataServiceContext context) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ProjectionAnalyzer.cs:line 61
   at Microsoft.OData.Client.ResourceBinder.AnalyzeProjection(MethodCallExpression mce, SequenceMethod sequenceMethod, Expression& e) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ResourceBinder.cs:line 597
   at Microsoft.OData.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ResourceBinder.cs:line 1586
   at Microsoft.OData.Client.ALinqExpressionVisitor.Visit(Expression exp) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ALinqExpressionVisitor.cs:line 85
   at Microsoft.OData.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\DataServiceExpressionVisitor.cs:line 44
   at Microsoft.OData.Client.ALinqExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ALinqExpressionVisitor.cs:line 251
   at Microsoft.OData.Client.ALinqExpressionVisitor.VisitMethodCall(MethodCallExpression m) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ALinqExpressionVisitor.cs:line 237
   at Microsoft.OData.Client.ResourceBinder.VisitMethodCall(MethodCallExpression mce) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ResourceBinder.cs:line 1599
   at Microsoft.OData.Client.ALinqExpressionVisitor.Visit(Expression exp) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ALinqExpressionVisitor.cs:line 85
   at Microsoft.OData.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\DataServiceExpressionVisitor.cs:line 44
   at Microsoft.OData.Client.ResourceBinder.Bind(Expression e, DataServiceContext context) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\ResourceBinder.cs:line 76
   at Microsoft.OData.Client.DataServiceQueryProvider.Translate(Expression e) in D:\a\_work\1\s\src\Microsoft.OData.Client\ALinq\DataServiceQueryProvider.cs:line 191
   at Microsoft.OData.Client.DataServiceQuery`1.Translate() in D:\a\_work\1\s\src\Microsoft.OData.Client\DataServiceQueryOfT.cs:line 446
   at Microsoft.OData.Client.DataServiceQuery`1.get_RequestUri() in D:\a\_work\1\s\src\Microsoft.OData.Client\DataServiceQueryOfT.cs:line 107
   at Microsoft.OData.Client.Tests.ALinq.PreserveTypesAndAttributesTests.GetRequestUri(IQueryable query) in D:\a\_work\1\s\test\FunctionalTests\Microsoft.OData.Client.Tests\ALinq\PreserveTypesAndAttributesTests.cs:line 184
   at Microsoft.OData.Client.Tests.ALinq.PreserveTypesAndAttributesTests.OneLevelOfInheritaceClassQuery_UsesRightPropertyNames_WhenCastedToBaseClass() in D:\a\_work\1\s\test\FunctionalTests\Microsoft.OData.Client.Tests\ALinq\PreserveTypesAndAttributesTests.cs:line 76
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

@habbes
Copy link
Contributor

habbes commented Sep 25, 2024

@lawynn The test that fails uses entity types with both key attributes, Id property names, OriginalName attributes and inheritance. Maybe one or more of these conditions is affected by your changes. But all of these cases (either individually or combined) should be supported even with your changes. Maybe you could look into, possibly add more test cases to ensure we don't introduce regressions?

[Key("CustomerID")]
public class BaseCustomer
{
    [OriginalName("CustomerID")]
    public string Id { get; set; }
}

Here's the test that fails for reference: https://github.com/OData/odata.net/blob/main/test/FunctionalTests/Microsoft.OData.Client.Tests/ALinq/PreserveTypesAndAttributesTests.cs#L137

Added check for anonymous types when determining if a property is a key property.
Added IsAnonymousProperty, and IsAnonymousType extensions
@lawynn
Copy link
Author

lawynn commented Sep 25, 2024

@habbes the test is failing is due to the use of an anonymous type in the expression tree. I have added a short circuit in the case where the declaring type is an anonymous type. All tests again pass locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants