question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Custom ValueConverter from class to string ignores column type and unicode property settings

See original GitHub issue

I have created a custom value converter to convert from a class to a string and vice versa. When using this property in a Contains lambda the SQL generation for the WHERE IN clause does not take into consideration the property builder extension functions IsUnicode or HasColumnType. This results in a SQL statement where a varchar field is being cast to nvarchar(max) and the string values in the IN clause are unicode (N'my string').

This is a huge performance hit and I would expect the IsUnicode and HasColumnType would be good enough hints for the SQL generation engine to treat the strings as ASCII.

I have also tried adding CustomMappingHints to the ValueConverter which did not change the SQL generation at all either.

Steps to reproduce

public class ValueString
{
    private readonly string _value;

    public ValueString(string value)
    {
        _value = value;
    }

    public static implicit operator string(ValueString valueString)
    {
        return valueString._value;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is ValueString valueString))
           return false;

       return _value == valueString._value;
    }

    public override int GetHashCode()
    {
        return _value.GetHashCode();
    }

    public override string ToString()
    {
        return _value;
    }
}

public static class PropertyBuilderExtensions
{

    public static PropertyBuilder<ValueString> HasValueStringConversion<ValueString>(this PropertyBuilder<ValueString> propertyBuilder)
    {
        var converter = new ValueConverter<ValueString, string>(
            t => t.ToString(),
            s => new ValueString(s));

        return propertyBuilder.HasConversion(converter);
    }
}

public class MyClass
{
    public ValueString Hello { get; set; }
}

public class MyClassEntityConfiguration : IEntityTypeConfiguration<MyClass>
{
    public void Configure(EntityTypeBuilder<MyClass> builder)
    {
        ...
        builder.Property(e => e.Hello)
            .IsUnicode(false)
            .HasValueStringConversion();
    }
}

Sample call:

context.MyClass.Where(a => list.Contains(a.Hello));

Results in:

SELECT Hello FROM MyClass
WHERE CAST(Hello AS nvarchar(max)) IN (N'sample', N'test')

Further technical details

EF Core version: 3.1.2 Database provider: Microsoft.EntityFrameworkCore.SqlServer v3.1.2 Target framework: .NET Core 3.1 Operating system: Windows 10 Enterprise IDE: Rider

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
lukepfeiffer10commented, Sep 4, 2020

Thanks for the assistance, it is working now that the type is changed to IEnumerable<ValueString>. I think the implicit conversion between ValueString and string was causing unnecessary confusion for me on how the compiler would know what to do.

0reactions
lukepfeiffer10commented, Sep 4, 2020

I see what you mean. I’ll try that.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Value Conversions - EF Core
Value converters allow property values to be converted when reading from or writing to the database. This conversion can be from one value...
Read more >
Model Bulk Configuration - EF Core
How to apply bulk configuration during model building in Entity Framework Core via Metadata API, conventions or pre-convention ...
Read more >
How to read data ignoring ValueConverters
I got a custom ValueConverter that serializes objects as JSON and stores them as a STRING in the database. This works well, but...
Read more >
Reference Property could not be mapped
I have tried changing the AccountStatus type to be based on BaseObject and remove [Key] from AccountStatus but I get same message. I...
Read more >
Converter | ICU Documentation
Single-String: Simplest type of conversion to or from Unicode. The data is entirely contained within a single string. Character: Converting from the codepage...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found