2

I'm trying to generate a SQL MERGE statement from Entity Framework Core entity. To do so I need to convert all entity properties into SQL strings e.g:

bool   => 1 or 0
string => 'string'
int    => 123

It looks like EF Core uses class ValueConverterSelector as a factory for all different internal as well as custom value converters. I need to get it from context. How can I do it?


UPDATE: Thanks to Ivan Stoev, he proposed the following way to get converterSelector:

var converterSelector = context.GetInfrastructure().GetService<IValueConverterSelector>()
var converters = converterSelector.Select(entry.Metadata.ClrType, prop.Metadata.ClrType);
// Converters collection is empty ;(

I'm facing a new issue with it. By inspecting private fields I see that this selector has no converters registered. Hence I still can't get the right converter for each property for the entities. I need a converter selector with exact custom and built-in converters that EF is using. Any ideas?

enter image description here

2 Answers 2

2

You can obtain any of the EF Core context services by adding

using Microsoft.EntityFrameworkCore.Infrastructure;

which gives you access to the extensions methods defined in the AccessorExtensions class, and in particular GetService method.

So for the concrete question you would use something like this:

using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

var valueConverterSelector = dbContext.GetService<IValueConverterSelector>();

Not every property has associated value converter. Currently (EF Core 2.2) you can obtain the value converter for IProperty similar to how EF Core does it using a code snippet like this:

using Microsoft.EntityFrameworkCore.Metadata.Internal;

IProperty property;
var valueConverter = property.FindMapping()?.Converter ?? property.GetValueConverter();
Sign up to request clarification or add additional context in comments.

4 Comments

Great answer Ivan. Thank you. One thing, The selector that I'm getting has no converters registered and I'm still getting no converters when I call selector.Select(...). I need the exact selector that EF is using under the hood.. Or otherwise how do they convert values into SQL?
That's a different question. Initially I was thinking to put a note about usability of that service, but decided to just answer the concrete question at that time. Not sure what are you trying to achieve, this service is intended for getting the preferred type mappings.
I can only do property.Metadata.FindMapping() which returns me the mapping but Converter is always null for (at least for int and string). Same for property.Metadata.GetValueConverter()...
Which simply means there is no value converter associated with these properties.
1

To get SQL value for property using Entity Framework you would need to:

var entry = context.Entry(model);
var prop = entry.Properties.First(); // Let's say for the 1st one
var sqlValue = prop.Metadata
    .FindRelationalMapping()
    .GenerateProviderValueSqlLiteral(prop.CurrentValue);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.