How to get Column name and corresponding Database Type from DbContext in Entity Framework Core

前端 未结 3 1329
臣服心动
臣服心动 2020-12-01 21:10

Suppose I have this table:

How can I get the column name and database datatype from DbContext in Entity Framework Core?

Tips

3条回答
  •  爱一瞬间的悲伤
    2020-12-01 21:43

    Update (EF Core 3.x): Starting with EF Core 3.0, the metadata API has changed again - Relational() extensions have been removed, and properties have been replaced with Get and Set extension methods, so now the code looks like this:

    var entityType = dbContext.Model.FindEntityType(clrEntityType);
    
    // Table info 
    var tableName = entityType.GetTableName();
    var tableSchema = entityType.GetSchema();
    
    // Column info 
    foreach (var property in entityType.GetProperties())
    {
        var columnName = property.GetColumnName();
        var columnType = property.GetColumnType();
    };
    

    Update (EF Core 2.x): Starting with EF Core 2.0, the things have changed, so the original answer does not apply anymore. Now EF Core builds separate model for each database type, so the code is much simpler and uses directly the Relational() extensions:

    var entityType = dbContext.Model.FindEntityType(clrEntityType);
    
    // Table info 
    var tableName = entityType.Relational().TableName;
    var tableSchema = entityType.Relational().Schema;
    
    // Column info 
    foreach (var property in entityType.GetProperties())
    {
        var columnName = property.Relational().ColumnName;
        var columnType = property.Relational().ColumnType;
    };
    

    Original answer (EF Core 1.x):

    Getting the access to the associated metadata is much easier in EF Core compared to EF - you start from DbContext.Model property to get IModel, use GetEntityTypes or FindEntityType to get IEntityType, then GetProperties or FindProperty to get IProperty etc.

    However the problem is that EF Core allows you to use different setting fro different target database. In order to get the attributes corresponding to the current database used by the context, you need to get access to the IRelationalDatabaseProviderServices and use AnnotationProvider and TypeMapper properties to get the information needed.

    Here is an example:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Infrastructure;
    using Microsoft.EntityFrameworkCore.Internal;
    using Microsoft.EntityFrameworkCore.Storage;
    
    public class DbColumnInfo
    {
        public string Name;
        public string Type;
    }
    
    public static class RelationalDbHelpers
    {
        public static IEnumerable GetDbColums(this DbContext dbContext, Type clrEntityType)
        {
            var dbServices = dbContext.GetService();
            var relationalDbServices = dbServices.DatabaseProviderServices as IRelationalDatabaseProviderServices;
            var annotationProvider = relationalDbServices.AnnotationProvider;
            var typeMapper = relationalDbServices.TypeMapper;
    
            var entityType = dbContext.Model.FindEntityType(clrEntityType);
    
            // Not needed here, just an example 
            var tableMap = annotationProvider.For(entityType);
            var tableName = tableMap.TableName;
            var tableSchema = tableMap.Schema;
    
            return from property in entityType.GetProperties()
                   let columnMap = annotationProvider.For(property)
                   let columnTypeMap = typeMapper.FindMapping(property)
                   select new DbColumnInfo
                   {
                       Name = columnMap.ColumnName,
                       Type = columnTypeMap.StoreType
                   };
        }
    }
    

提交回复
热议问题