如何從Entity Framework Core中的DbContext獲取列名和相應的數據庫類型

.net-core c# entity-framework entity-framework-core

假設我有這個表:

在此處輸入圖像描述

如何從Entity Framework Core中的DbContext獲取列名和數據庫數據類型?

提示

  1. 名為clg#的列由EF Core Scaffold工具轉換為clg1,因此我需要真正的列名而不是當前的EF名稱

  2. 我需要數據庫類型,而不是clrType,當然必須是跨平台。也許我會改變數據庫,所以方法也必須工作。

期望的結果:

    <D.clg#, int>
    <D.clgname, nvarchar(50)>
    <D.city, nvarchar(50)>
    <D.pname, nvarchar(50)>

誰能提供解決方案?

一般承認的答案

更新:從EF Core 2.0開始,情況發生了變化,因此原始答案不再適用。現在EF Core為每種數據庫類型構建單獨的模型,因此代碼更簡單並直接使用Relational()擴展:

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;
};

原始答案(EF Core 1.x):

與EF相比,在EF Core中訪問相關元數據要容易得多 - 從DbContext.Model屬性開始獲取IModel ,使用GetEntityTypesFindEntityType獲取IEntityType ,然後使用GetPropertiesFindProperty獲取IProperty等。

但問題是EF Core允許您對不同的目標數據庫使用不同的設置。為了獲取與上下文使用的當前數據庫相對應的屬性,您需要訪問IRelationalDatabaseProviderServices並使用AnnotationProviderTypeMapper屬性來獲取所需的信息。

這是一個例子:

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<DbColumnInfo> GetDbColums(this DbContext dbContext, Type clrEntityType)
    {
        var dbServices = dbContext.GetService<IDbContextServices>();
        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
               };
    }
}


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow