このテーブルがあるとしましょう:
Entity Framework CoreでDbContext
から列名とデータベースデータ型を取得するにはどうすればよいですか?
チップ
Clg#という名前の列がEF Core Scaffoldツールによってclg1に変換されたため、現在のEF名ではなく実際の列名が必要
もちろん、clrTypeではなくデータベースタイプが必要です。もちろん、クロスプラットフォームである必要があります。多分私はデータベースを変更するので、メソッドも機能する必要があります。
望ましい結果:
<D.clg#, int>
<D.clgname, nvarchar(50)>
<D.city, nvarchar(50)>
<D.pname, nvarchar(50)>
誰かが解決策を提供できますか?
更新(EF Core 3.x):EF Core 3.0以降、メタデータAPIが再び変更されました-Relational()
拡張機能が追加されました削除され、プロパティはGet
およびSet
拡張メソッドに置き換えられたため、コードは次のようになります。
_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();
};
_
更新(EF Core 2.x):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
を取得し、GetEntityTypes
を使用するか、 FindEntityType
を取得するには IEntityType
、次にGetProperties
またはFindProperty
を取得するには IProperty
=など.
ただし、問題はEF Coreを使用すると、さまざまなターゲットデータベースでさまざまな設定を使用できることです。コンテキストで使用されている現在のデータベースに対応する属性を取得するには、 IRelationalDatabaseProviderServices
にアクセスし、 AnnotationProvider
を使用する必要があります=および TypeMapper
必要な情報を取得するためのプロパティ。
次に例を示します。
_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
};
}
}
_
ここに到着したが、私のように.NET COREを使用していない人向け。これを試して:
public partial class MyDbContext : System.Data.Entity.DbContext
{
public string GetTableName(Type entityType)
{
var sql = Set(entityType).ToString();
var regex = new Regex(@"FROM \[dbo\]\.\[(?<table>.*)\] AS");
var match = regex.Match(sql);
return match.Groups["table"].Value;
}
public string[] GetColumnName(Type entityType)
{
var strs = new List<string>();
var sql = Set(entityType).ToString();
var regex = new Regex(@"\[Extent1\]\.\[(?<columnName>.*)\] AS");
var matches = regex.Matches(sql);
foreach (Match item in matches)
{
var name = item.Groups["columnName"].Value;
strs.Add(name);
}
return strs.ToArray();
}
}
多分冗長ですが、時間を節約できます。
アントニオ