0

How do I find the DataType of Metadata.IProperty in Entity Framework Core?

var tableType = _dbContext.Model.GetEntityTypes().First(c => c.GetTableName() == tableName);
foreach (var property in tableType.GetProperties())
{
     var test = property.PropertyInfo.PropertyType.Name;

Using property.PropertyInfo.PropertyType.Name, sometimes works, however for nullable objects it prints null. I am looking for a clean way to get data type.

enter image description here

3 Answers3

0

You may look for this:Get PropertyType.Name in reflection from Nullable type

var propertyType = propertyInfo.PropertyType;

if (propertyType.IsGenericType &&
        propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
    {
      propertyType = propertyType.GetGenericArguments()[0];
    }

model.ModelProperties.Add(new KeyValuePair<Type, string>
                        (propertyType.Name,propertyInfo.Name));
YannXu
  • 1
  • I just tried propertyInfo.PropertyType.Name, and sometimes it gives me a null, I am writing to fix that –  Nov 27 '20 at 04:02
0

Since you are already using PropertyType.Name, I'm assuming that you are expecting a string denoting the name of the types, and not more information about the types.

  1. You can use IProperty.ClrType to get the data type of an IProperty
  2. You can detect nullability of a type with Nullable.GetUnderlyingType()
  3. Nullable types are basically generic types, Nullable<T>, so you can obtain the type arguments with Type.GenericTypeArguments property

Combining the facts above you can create an extension method like -

public static string GetPropertyType(this IProperty property)
{
    return Nullable.GetUnderlyingType(property.ClrType) != null
        ? nameof(Nullable) + "<" + property.ClrType.GenericTypeArguments.First().Name + ">"
        : property.PropertyInfo.PropertyType.Name;
}

Now, nullable or not, you can get a "clean" string for the data type name -

var tableType = _dbContext.Model.GetEntityTypes().First(c => c.GetTableName() == tableName);
foreach (var property in tableType.GetProperties())
{
     var test = property.GetPropertyType();
}
atiyar
  • 7,762
  • 6
  • 34
  • 75
0

The Type of the IProperty is represented by ClrType property. It handles correctly both real properties (having PropertyInfo), fields (EF Core 5.0+ allow mapping fields as properties), and also shadow properties which have no assocaited PropertyInfo or FieldInfo at all.

var tableType = _dbContext.Model.GetEntityTypes().First(c => c.GetTableName() == tableName);
foreach (var property in tableType.GetProperties())
{
    Type type = property.ClrType;
}

Now speaking about string representation of that Type, it is arbitrary (similar any formatting) and depends on your needs. For instance, for debug display purposes EF Core internally uses the ShortDisplayName method. You can eventually use it, but note that it uses C# built-in types (e.g. int instead of Int32) and formats nullable type as "Nullable<{TypeName}>" e.g.

Requires

using Microsoft.EntityFrameworkCore.Infrastructure;

and then

var tableType = _dbContext.Model.GetEntityTypes().First(c => c.GetTableName() == tableName);
foreach (var property in tableType.GetProperties())
{
    var type = property.ClrType;
    var typeName = type.ShortDisplayName();
}

Again, converting Type to string differs, and depends on what this string will be used for. So use Type instead of string where possible. GetColumnType is different - it returns string because there is no class similar to Type to represent the database provider types.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343