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

Need discussion of Value Comparers #1986

Closed
IndigoHealth opened this issue Dec 12, 2019 — with docs.microsoft.com · 14 comments · Fixed by #2192
Closed

Need discussion of Value Comparers #1986

IndigoHealth opened this issue Dec 12, 2019 — with docs.microsoft.com · 14 comments · Fixed by #2192

Comments

Copy link

So, I got this surprisingly helpful warning message, telling me that my POCO property has a value converter but no value comparer. I had followed the guidance on this page and declared a value converter, but it took a lot of digging to come up with this SO answer that showed how to declare and wire up a value comparer.

The SO answer includes a bunch of undocumented magic, in particular propertyBuilder.Metadata.SetValueConverter and propertyBuilder.Metadata.SetValueComparer.

Since creation of a value converter apparently implies the necessity of creating a value comparer, please discuss this subject in this article.


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@ajcvickers
Copy link
Contributor

ajcvickers commented Dec 12, 2019

Part of #614

@ajcvickers
Copy link
Contributor

Oops. That was for converters. Agree we need docs here.

Copy link

SidShetye commented Dec 16, 2019

Also shouldn't there be a default comparer for each primitive type? We have a custom string -> string converter but we still want a string comparer at the end of the day.

Edit: To add, the framework should realize this and use those default comparers instead of raising a warning.

@ajcvickers
Copy link
Contributor

ajcvickers commented Dec 16, 2019

@SidShetye There is. EF does use the default. But the default may not be correct.

Copy link

dansoper commented Jan 9, 2020

Is this the same as #1680? That doesn't seem to be linked to this page, though.

@ajcvickers
Copy link
Contributor

See also #1680. Make sure this relates to collection conversions.

@SidShetye
Copy link

SidShetye commented Jan 30, 2020

@ajcvickers till the documentation comes up, is this the correct approach for ValueComparers to avoid warnings with custom converters?

string

property.SetValueConverter(new MyConverter<string>());
property.SetValueComparer(new ValueComparer<string>(
	(l, r) => string.Equals(l, r, StringComparison.Ordinal),
	v => StringComparer.Ordinal.GetHashCode(v),
	v => v)
);

and

byte[]

property.SetValueConverter(new MyConverter<byte[]>());
property.SetValueComparer(new ValueComparer<byte[]>(
	(l, r) => (l == null || r == null) ? (l == r) : l.SequenceEqual(r),
	v => v.GetHashCode())
);

where property is Microsoft.EntityFrameworkCore.Metadata.IMutableProperty and the .SetValueConverter(), .SetValueComparer() methods come from Microsoft.EntityFrameworkCore.MutablePropertyExtensions

@ajcvickers
Copy link
Contributor

ajcvickers commented Jan 30, 2020

@SidShetye Looks like you are trying to configure compares for the database type. It's the type in your model (the type that is being converted to byte[] or string) that needs to be compared.

@SidShetye
Copy link

@ajcvickers We're transforming the values/contents, not the type itself. So byte[] remains byte[] and string remains string after the converters. The comparers seem silly/redundant but seems like it's the only way to avoid the EF Core warning.

Thoughts?

@ajcvickers
Copy link
Contributor

@SidShetye That sounds like it could be a bug. Please post a small, runnable project that reproduces this so we can investigate.

ajcvickers added a commit that referenced this issue Mar 19, 2020
ajcvickers added a commit that referenced this issue Mar 20, 2020
ajcvickers added a commit that referenced this issue Mar 20, 2020
@ajcvickers
Copy link
Contributor

Still need to update the fwlink.

@JimInNC
Copy link

JimInNC commented Apr 8, 2021

I am hunting the internet for a good explanation of using the ValueConverter in my EF Core Db Context. Following is a snippet from my context. Is this snippet supposed to convert UTC from the database in to Local, and convert Local to UTC when SaveChanges() to the database?

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
             ValueConverter<DateTime, DateTime> dateTimeConverter = new ValueConverter<DateTime, DateTime>(
               v => v.ToLocalTime(),
               v => DateTime.SpecifyKind(v, DateTimeKind.Utc));

            ValueConverter<DateTime?, DateTime?> nullableDateTimeConverter = new ValueConverter<DateTime?, DateTime?>(
                v => v.HasValue ? v.Value.ToLocalTime() : v,
                v => v.HasValue ? DateTime.SpecifyKind(v.Value, DateTimeKind.Utc) : v);

            foreach (var entityType in modelBuilder.Model.GetEntityTypes())
            {
                if (entityType.IsKeyless)
                {
                    continue;
                }

                foreach (var property in entityType.GetProperties())
                {
                    if (property.ClrType == typeof(DateTime))
                    {
                        property.SetValueConverter(dateTimeConverter);

                        property.SetValueComparer(new ValueComparer<DateTime>(
                            (l, r) => l == r,
                            v => StringComparer.Ordinal.GetHashCode(v),
                            v => v)
                        );
                    }
                    else if (property.ClrType == typeof(DateTime?))
                    {
                        property.SetValueConverter(nullableDateTimeConverter);

                        property.SetValueComparer(new ValueComparer<DateTime?>(
                           (l, r) => l == r,
                           v => StringComparer.Ordinal.GetHashCode(v),
                           v => v)
                       );
                    }
                }
            }

@ajcvickers
Copy link
Contributor

@JimInNC We have docs with many examples and sample code that can be downloaded from GitHub.

@JimInNC
Copy link

JimInNC commented Apr 8, 2021 via email

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

Successfully merging a pull request may close this issue.

5 participants