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

Check parameters for nullable types in EF.Functions extensions #26634

Open
joakimriedel opened this issue Nov 11, 2021 · 15 comments
Open

Check parameters for nullable types in EF.Functions extensions #26634

joakimriedel opened this issue Nov 11, 2021 · 15 comments
Labels
area-model-building area-query customer-reported providers-beware punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. type-enhancement
Milestone

Comments

@joakimriedel
Copy link
Contributor

I'm currently spending this week annotating a large project to .NET 6.

In this process I have some code that calls EF.Functions.Like with a property that is now of type nullable string string?. This will produce a warning since this method is annotated to only accept non-nullable string.

See

string matchExpression,

I think it should be string? matchExpression ?

@roji
Copy link
Member

roji commented Nov 11, 2021

Thanks for the feedback. This was discussed a few times in the past - what's your argument for annotating this as nullable?

@joakimriedel
Copy link
Contributor Author

joakimriedel commented Nov 11, 2021

@roji

In my code I've got something similar to ..

dbQuery = dbQuery.Where(c =>
    EF.Functions.Like(c.Company, likeMatch) ||
    EF.Functions.Like(c.FirstName, likeMatch) ||
    EF.Functions.Like(c.LastName, likeMatch) ||
    EF.Functions.Like(c.Email, likeMatch) ||
    EF.Functions.Like(c.PhoneNumber, likeMatch)
    );

.. to quickly search entities by any key. A contact is defined as

    public class Contact
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public string? Company { get; set; }
        public string? Email { get; set; }
        public string? PhoneNumber { get; set; }
    }

where all fields are optional.

On upgrade to .NET 6, I get a squiggly warning in Visual Studio 2022 like this

image

I would prefer not to have to force not-null them, since they can be null and SQL LIKE supports null in raw query such as

select * from Contacts where FirstName like '%foo%'

@ajcvickers
Copy link
Contributor

@joakimriedel The types used here have been a source of debate over the last few years. There are advantages in constraining them, but also advantages in completely opening them up--see #20962.

@joakimriedel
Copy link
Contributor Author

@ajcvickers I'm not sure how it is with other providers, but SQL Server is perfectly happy to use an int or datetime2 column as source for LIKE as well since it will be magically converted to character string type.

I would support having multiple overloads such as

public static bool Like(this DbFunctions _, string? matchExpression, string pattern)
public static bool Like(this DbFunctions _, int? matchExpression, string pattern)
public static bool Like(this DbFunctions _, DateTime? matchExpression, string pattern)

but my main concern is that it's currently annotated string and not string? is there any drawbacks by changing that?

@ajcvickers
Copy link
Contributor

@joakimriedel That question results in heated debate on the team. :-) I'm not sure that I fully understand both sides of the argument, so I will refrain from commenting more at this time. The "needs-design" label indicates that we need to discuss this more and come to a conclusion.

@ajcvickers
Copy link
Contributor

We have discussed this and come to the conclusion that we will make the parameters nullable. The arguments against are that the BCL methods for similar kinds of function mapping do not allow nulls, and often for this kind of function it makes sense not to allow nulls from the C# perspective. On the other hand, most SQL functions allow null, and return null if null is passed. To match this, we would need to return a nullable type, but this is quite inconvenient in C# code. However, the functions are often used in translations where the return value is never materialized to a C# value, for example in a WHERE clause. In this case, passing null is useful and the return is handled by SQL. (Although see #26735.)

So...since these are methods only used to translate to SQL, we will make the parameters nullable, but not change the return types to nullable. This applies to Like, and @smitpatel will make a pass to determine which other methods should be changed similarly.

@joakimriedel
Copy link
Contributor Author

Sounds good, this will make it easier to migrate to net 6 without any null-forgiving. Thanks!

@ajcvickers ajcvickers added this to the 7.0.0 milestone Nov 19, 2021
@roji roji changed the title EF.Functions.Like should be annotated to accept nullable string? Annotate all parameters as nullable in EF.Functions extensions Nov 19, 2021
@roji
Copy link
Member

roji commented Nov 19, 2021

BTW there's the question of value type parameters - we could also make those nullable; that would be a small binary break.

@smitpatel smitpatel changed the title Annotate all parameters as nullable in EF.Functions extensions Check parameters for nullable reference types in EF.Functions extensions Nov 19, 2021
@smitpatel
Copy link
Contributor

We are not making all parameters nullable.

@roji
Copy link
Member

roji commented Nov 19, 2021

The question is whether a parameter is a reference of value type should play a role in the decision, and why.

@smitpatel
Copy link
Contributor

My comment was directed toward incorrect title of the issue. Nullability of parameter is based on our decision regardless of value type or reference type.

@roji roji changed the title Check parameters for nullable reference types in EF.Functions extensions Check parameters for nullable types in EF.Functions extensions Nov 19, 2021
@roji
Copy link
Member

roji commented Nov 19, 2021

👍

@ajcvickers ajcvickers added punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. and removed propose-punt labels Jul 7, 2022
@ajcvickers ajcvickers removed this from the 7.0.0 milestone Jul 7, 2022
@ajcvickers ajcvickers added this to the Backlog milestone Jul 7, 2022
@smitpatel smitpatel removed their assignment Sep 14, 2022
@Akridian
Copy link

Akridian commented Jun 6, 2023

Any updates on this subject? Got strange issue where o.Name != null && EF.Functions.Like(o.Name, term) still produces warning when multiple checks joined by ||. Was forced to use null-forgiving operator and not happy with it.

@roji
Copy link
Member

roji commented Jun 6, 2023

This still hasn't been done, so using the null-forgiving operator is currently the way to go.

@roji
Copy link
Member

roji commented Aug 16, 2023

Note that for EF.Functions.Like specifically, parameters have been made nullable in #31482.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-model-building area-query customer-reported providers-beware punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. type-enhancement
Projects
None yet
Development

No branches or pull requests

5 participants