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

Use table mappings for FromSql #32816

Closed
wants to merge 1 commit into from
Closed

Use table mappings for FromSql #32816

wants to merge 1 commit into from

Conversation

ajcvickers
Copy link
Member

The difference between the DbSet queries (work) and the FromSql queries (don't work) is that the DbSet queries use the table mappings, while the FromSql queries use the default mappings. The default mappings don't contain complex types. This may be an issue in of itself.

Fixes #32699

The difference between the DbSet queries (work) and the FromSql queries (don't work) is that the DbSet queries use the table mappings, while the FromSql queries use the default mappings. The default mappings don't contain complex types. This may be an issue in of itself.

Fixes #32699
@@ -483,8 +483,8 @@ SELECT 1
SELECT "OrderID", "ProductID", "UnitPrice", "Quantity", "Discount"
FROM "Order Details"
WHERE "OrderID" < 10300
) AS [m]
Copy link
Member Author

Choose a reason for hiding this comment

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

@roji This changed aliases in a few places. I didn't dig into why, since you are changing the alias generation code anyway, right?

Copy link
Member

Choose a reason for hiding this comment

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

I'm guessing that having an actual relational Table from the table mappings above (as opposed to a TableBase from the default mappings) - with the actual table name - makes us use its name as the alias; that actually looks like an improvement to me (I've done some stuff in #32785 but didn't really look at FromSql specifically).


[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Filter_on_property_inside_nested_complex_type_with_FromSql(bool async)
Copy link
Member

Choose a reason for hiding this comment

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

Not necessarily a problem, but does the filtering inside the SQL add any actual coverage across all these variants? The thing that gets projected out of the SQL is the same, so in effect are these checking something beyond that the database performed the SQL WHERE correctly?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, I just added a few tests doing various things, since we didn't have any coverage of FromSql with complex types.

Copy link
Member

Choose a reason for hiding this comment

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

Up to you, but I'd consider not adding tests if they don't add any coverage (maintenance, test running time...)

async,
ss => ((DbSet<Customer>)ss.Set<Customer>()).FromSql(
$"""
SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_Tags], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_Tags], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName]
Copy link
Member

Choose a reason for hiding this comment

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

nit: align the SQL to the left like in the above tests

@@ -483,8 +483,8 @@ SELECT 1
SELECT "OrderID", "ProductID", "UnitPrice", "Quantity", "Discount"
FROM "Order Details"
WHERE "OrderID" < 10300
) AS [m]
Copy link
Member

Choose a reason for hiding this comment

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

I'm guessing that having an actual relational Table from the table mappings above (as opposed to a TableBase from the default mappings) - with the actual table name - makes us use its name as the alias; that actually looks like an improvement to me (I've done some stuff in #32785 but didn't really look at FromSql specifically).

@@ -104,7 +104,8 @@ protected override Expression VisitExtension(Expression extensionExpression)
_sqlExpressionFactory.Select(
fromSqlQueryRootExpression.EntityType,
new FromSqlExpression(
fromSqlQueryRootExpression.EntityType.GetDefaultMappings().Single().Table,
fromSqlQueryRootExpression.EntityType.GetTableMappings().SingleOrDefault()?.Table
Copy link
Member

Choose a reason for hiding this comment

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

OK, I see...

First, yeah, I wonder whether the right fix isn't to have the table returned by GetDefaultMappings have mappings to the entity type's complex types; in other words, is this a metadata bug rather than a query bug (/cc @AndriySvyryd).

If not, then about this specific fix: this looks like it will throw for entity splitting (no longer a single table for the entity type); it also hard-codes a preference for querying the tables (over e.g. views) when using FromSql(), which I'm not sure is right...

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure it's right either, but then it doesn't seem like using a DbSet with FromSql should be any different from using a DbSet without FromSql.

Copy link
Member

Choose a reason for hiding this comment

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

Let's see what @AndriySvyryd has to say about all this... Don't we support defining both a view and a table mapping for an entity type, in which case querying its DbSet would query the view?

@ajcvickers
Copy link
Member Author

If there is a view defined, then again shouldn't a FromSql query do the same as a normal query?

@roji
Copy link
Member

roji commented Jan 15, 2024

If there is a view defined, then again shouldn't a FromSql query do the same as a normal query?

I think so, but doesn't this PR's change hard-code FromSql to prefer table bindings if they exist, over the default ones? I'm not great with metadata, but doesn't that mean we'd suddenly switch over to querying the table instead of the view when doing FromSql?

@ajcvickers
Copy link
Member Author

I think so, but doesn't this PR's change hard-code FromSql to prefer table bindings if they exist, over the default ones?

Yes, because that's what we do for DbSets. At least, that's the difference I found when debugging this. I agree that I don't know if this is right or not.

@roji
Copy link
Member

roji commented Jan 15, 2024

I'm confused :) Maybe let's discuss in triage/design...

@AndriySvyryd
Copy link
Member

FromSql uses the default mappings to avoid depending on how tables are mapped and as a stepping stone towards #21627

@ajcvickers
Copy link
Member Author

@AndriySvyryd Shay and I were talking about this earlier, and I expect the default mappings are very under-tested when it comes to queries. We should do a review of all the places that query requests a mapping and check that it is requesting the right thing, and then check we have tests for all the cases where we select or fall back to the default mappings.

@AndriySvyryd
Copy link
Member

Filed #32853

@roji
Copy link
Member

roji commented Jan 18, 2024

Should we use #32699 to track adding complex types to the default mappings?

ajcvickers added a commit that referenced this pull request Jan 19, 2024
Replaces #32816
Fixes #32699

As discussed, leaving FromSql to use the default mappings, but add complex types to the default mappings.
@ajcvickers
Copy link
Member Author

Replaced by #32867

@ajcvickers ajcvickers closed this Jan 19, 2024
ajcvickers added a commit that referenced this pull request Jan 23, 2024
Replaces #32816
Fixes #32699

As discussed, leaving FromSql to use the default mappings, but add complex types to the default mappings.
ajcvickers added a commit that referenced this pull request Jan 23, 2024
* Add complex type mappings to the default relational mappings

Replaces #32816
Fixes #32699

As discussed, leaving FromSql to use the default mappings, but add complex types to the default mappings.

* Add note to SelectExpression
ajcvickers added a commit that referenced this pull request Jan 23, 2024
* Add complex type mappings to the default relational mappings

Replaces #32816
Fixes #32699

As discussed, leaving FromSql to use the default mappings, but add complex types to the default mappings.

* Add note to SelectExpression
ajcvickers added a commit that referenced this pull request Jan 23, 2024
* Add complex type mappings to the default relational mappings

Replaces #32816
Fixes #32699

As discussed, leaving FromSql to use the default mappings, but add complex types to the default mappings.

* Add note to SelectExpression
maumar pushed a commit that referenced this pull request Feb 7, 2024
…pings (#32901)

* Add complex type mappings to the default relational mappings (#32867)

* Add complex type mappings to the default relational mappings

Replaces #32816
Fixes #32699

As discussed, leaving FromSql to use the default mappings, but add complex types to the default mappings.

* Add note to SelectExpression

* Fix merge and add quirks
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.

Exception when using FromSql on entity with ComplexProperty
3 participants