假设我有这张表:
如何从Entity Framework Core中的#include <Wire.h>
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(115200); // start serial for output
}
void loop() {
delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
Serial.println("Received..");
/*
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
*/
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}
获取列名和数据库数据类型?
提示
名称为clg#的列由EF Core Scaffold工具转换为clg1所以我需要真正的列名而不是当前的EF名称
我需要数据库类型,而不是clrType,当然必须是跨平台。也许我会更改数据库,因此该方法也必须正常工作。
期望的结果:
DbContext
有人能提供解决方案吗?
答案 0 :(得分:14)
更新:从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
};
}
}
答案 1 :(得分:1)
对于那些来到这里但没有使用.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();
}
}
也许是多余的,但可以节省时间。
antonio
答案 2 :(得分:0)
基于EFC3.1的答案,我创建了此帮助程序,用于将所有表名和列名存储到第一次使用时填充的单例字典中,因此代码不必遍历所有内容。我们将其用于NPGSQL批量复制操作,它似乎可以正常工作。该版本不会从实体类中过滤掉任何属性,因此在进行列名列表/字符串时,请注意字段的顺序。但是再一次,据我了解,您将仅获得在上下文中映射的属性,因此一切正常。
助手
public class ContextHelper
{
private readonly ILogger<ContextHelper> logger;
private readonly ApplicationDbContext context;
private static Dictionary<Type, string> tableNames = new Dictionary<Type, string>(30);
private Dictionary<Type, Dictionary<string, string>> columnNames = new Dictionary<Type, Dictionary<string, string>>(30);
public ContextHelper(ILogger<ContextHelper> logger, ApplicationDbContext context)
{
this.logger = logger;
this.context = context;
PopulateTableNames();
PopulateColumnNames();
}
private void PopulateTableNames()
{
logger.LogInformation("Populating table names in context helper");
foreach (var entityType in context.Model.GetEntityTypes())
{
tableNames.Add(entityType.ClrType, entityType.GetTableName());
}
}
private void PopulateColumnNames()
{
logger.LogInformation("Populating column names in context helper");
foreach (var entityType in context.Model.GetEntityTypes())
{
var clrType = entityType.ClrType;
if (!columnNames.ContainsKey(clrType))
{
columnNames.Add(clrType, new Dictionary<string, string>(30));
}
foreach (var property in entityType.GetProperties())
{
columnNames[clrType].Add(property.Name, property.GetColumnName());
}
}
}
public string GetTableName<T>()
{
return context.Model.FindEntityType(typeof(T)).GetTableName();
}
public string GetColumnName<T>(string propertyName)
{
return columnNames[typeof(T)][propertyName];
}
public List<string> GetColumnNames<T>()
{
return columnNames[typeof(T)].Select(x => x.Value).ToList();
}
}
启动注册
services.AddSingleton<ContextHelper>();
用法,类似的话
var columnNames = contextHelper.GetColumnNames<OvenEventLog>().Where(x=>x != contextHelper.GetColumnName<OvenEventLog>(nameof(OvenEventLog.IdLog)));
var separatedCN = string.Join(", ", columnNames);
using (var writer = conn.BeginBinaryImport(
$"COPY {contextHelper.GetTableName<OvenEventLog>()} ({separatedCN}) FROM STDIN (FORMAT BINARY)")