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

Fix duplicate JOIN statements when expanding an IQueryable that already has a join #1040

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

Conversation

ElizabethOkerio
Copy link
Contributor

@ElizabethOkerio ElizabethOkerio commented Sep 4, 2023

Fixes #1035

In this fix #993 we added a fix to remove duplicate joins from the generated sql. This involved making updates to the Instance property of the expression to be created and only including structural properties.

The changes led to this being generated:

{ Instance = new Customer() {Id = $it.Id, Name= $it.Name}}

Instead of this:

{ Instance = $it }

These changes did not take into consideration query settings. I've added checks for nullability and handling null propagation and creating a conditional expression.

@ElizabethOkerio ElizabethOkerio changed the title Fix $expand with null properties Fix $expand with null navigation properties Sep 4, 2023
}
else if (isSourceNullable)
{
object defaultValue = prop.PropertyType.IsValueType ? Activator.CreateInstance(prop.PropertyType) : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about if the property type doesn't have the default constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All value types have a default constructor. So I don't think there will ever be a case where the property type does not have a default constructor. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/types#833-default-constructors

foreach (var sp in structuralProperties)
{
if (prop.CanWrite && model.GetClrPropertyName(sp) == prop.Name)
{
MemberExpression propertyExpression = Expression.Property(source, prop);
bindings.Add(Expression.Bind(prop, propertyExpression));
Expression propertyValue = Expression.Property(source, prop);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we create a test case to test a big schema, for example, more than 1k properties for an entity type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to have an entity type with more than 1k properties?

@ElizabethOkerio ElizabethOkerio force-pushed the fix/expand_with_null_navigation_properties branch from da83272 to d504172 Compare November 6, 2023 11:20
@ElizabethOkerio ElizabethOkerio changed the title Fix $expand with null navigation properties Fix duplicate JOIN statement when expanding an IQueryable that already has a join Nov 6, 2023
@ElizabethOkerio ElizabethOkerio changed the title Fix duplicate JOIN statement when expanding an IQueryable that already has a join Fix duplicate JOIN statements when expanding an IQueryable that already has a join Nov 6, 2023
Orders = new List<QueryOrder>()
};

QueryOrder order1 = new QueryOrder { Id = 42, Title = "The order", Customer = customer1 };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us stick to var for consistency.

@@ -82,7 +84,19 @@ public SelectExpandBinderTest()
QueryOrder order = new QueryOrder { Id = 42, Title = "The order", Customer = customer };
customer.Orders.Add(order);

QueryCustomer customer1 = new QueryCustomer

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us stick to var for consistency.

// as observed here: https://github.com/OData/AspNetCoreOData/issues/497

Expression updatedExpression = null;
if (IsEfQueryProvider(context))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

           var updatedExpression = source;
            if (IsEfQueryProvider(context))
            {
                updatedExpression = RemoveNonStructuralProperties(context, source, structuredType);
            }

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.

Optional Navigations Broken (Nullable object must have a value)
3 participants