如何在 EF Core 中获取数据库 table 主键列的列表

How to get list of database table primary key columns in EF Core

ASP.NET 使用 EF Core 的核心 MVC 应用程序。在 Linq to SQL 中,此代码 returns 数据库列表 table 主键列名称:

    /// <summary>
    /// Database primary key names
    /// </summary>
    public IList<string> DatabasePrimaryKey(Type dbContextPocoType)
    {
        List<string> pk = new List<string>();

        foreach (PropertyInfo p in dbContextPocoType.GetProperties())
        {
            var ca = p.GetCustomAttributes(typeof(ColumnAttribute), true);

            if (ca.Length == 0) continue;
            var atr = (ColumnAttribute)ca.Single();

            if (!atr.IsPrimaryKey) continue;
            pk.Add(atr.Name);
        }

        return pk;
    }

我在 EF Core 中尝试过

var entry = ctx.Entry(dbContextPocoType);
var primaryKey = entry.Metadata.FindPrimaryKey();

IList<string>  keys = primaryKey.Properties.Select(x => x.Name).ToList();
return keys;

但是这个 returns C# 属性 名称 - 如何在 EF Core 中获取数据库 table 列名称?

更新: 使用答案我创建了这个方法:

    public IList<string> DatabasePrimaryKey<TPoco>()
    {
        var entry = ctx.Entry(typeof(TPoco));
        var primaryKey = entry.Metadata.FindPrimaryKey();
        var entityType = ctx.Model.FindEntityType(typeof(TPoco).Name);
        var schema = entityType.GetSchema();
        var tableName = entityType.GetTableName();
        IList<string> keys = primaryKey.Properties
             .Select(x => x.GetColumnName(StoreObjectIdentifier.Table(tableName, schema)))
             .ToList();
        return keys;
    }

这个方法可以改进吗?

在 EF Core 中 3.x 您可以尝试 IProperty 扩展方法 GetColumnName

var entry = ctx.Entry(dbContextPocoType);
var primaryKey = entry.Metadata.FindPrimaryKey();
var primaryKeyColumns = primaryKey.Properties
                     .Select(property => property.GetColumnName())
                     .ToList()

return primaryKeyColumns;

对于 EF Core 5,您需要使用接受 StoreObjectIdentifier 的重载:GetColumnName(IProperty, StoreObjectIdentifier)

EF 5 更新:

public IList<string> DatabasePrimaryKey<TPoco>()
{
    var entityType = ctx.Model.FindEntityType(typeof(TPoco));
    var primaryKey = entityType.FindPrimaryKey();
    var schema = entityType.GetSchema();
    var tableName = entityType.GetTableName();
    var storeObjectIdentifier = StoreObjectIdentifier.Table(tableName, schema);
    IList<string> primaryKeyColumns = primaryKey.Properties
        .Select(x => x.GetColumnName(storeObjectIdentifier))
        .ToList();
    return primaryKeyColumns;
}