You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core动态获取DbSet并调用FirstOrDefault方法遇阻求助

问题解决与代码修正

1. 为什么PropertyInfo返回null?

你当前用entityType.Name作为属性名称去查找,逻辑完全错误——实体类几乎不会存在与自身类名同名的属性。正确的做法是直接从EF Core的ForeignKey对象中获取关联的导航属性,不需要手动反射查找:

// 从外键获取对应的导航属性
var navigation = foreignKey.GetNavigation();
// 导航属性名称
var navigationName = navigation.Name;
// 导航属性对应的类型
var navigationType = navigation.ClrType;

2. 如何动态调用FirstOrDefault?

DbContext提供了非泛型的Set(Type)方法,可直接传入实体类型获取对应的DbSet,再通过Queryable静态方法调用FirstOrDefault:

修正后的完整代码示例

using System.Reflection;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

public static List<string> GetAllRelations<T>(DbContext db, T entity) where T : class
{
    var result = new List<string>();
    var model = db.Model;
    var userEntity = model.FindEntityType(typeof(T));
    var primaryKey = userEntity.FindPrimaryKey();

    // 获取所有引用当前实体主键的外键
    var referencingForeignKeys = model.GetEntityTypes()
        .SelectMany(e => e.GetForeignKeys())
        .Where(fk => fk.PrincipalKey == primaryKey)
        .ToList();

    foreach (var foreignKey in referencingForeignKeys)
    {
        var declaringEntityType = foreignKey.DeclaringEntityType;
        var entityFullName = declaringEntityType.Name;
        var entityType = Assembly.GetAssembly(typeof(BaseEntities)).GetType(entityFullName);
        
        if (entityType == null) 
            continue;

        // 1. 获取导航属性(替代你原来错误的PropertyInfo查找)
        var navigation = foreignKey.GetNavigation();
        var navigationName = navigation.Name;
        result.Add($"关联实体:{declaringEntityType.DisplayName()},导航属性:{navigationName}");

        // 2. 动态调用FirstOrDefault查询数据
        var dbSet = db.Set(entityType);
        var queryable = dbSet.AsQueryable();
        // 通过表达式树调用FirstOrDefault
        var firstEntity = queryable.Provider.Execute(
            Expression.Call(
                typeof(Queryable), 
                nameof(Queryable.FirstOrDefault), 
                new[] { entityType }, 
                queryable.Expression
            )
        );

        if (firstEntity != null)
        {
            result.Add($"找到{declaringEntityType.Name}的第一条数据");
        }
    }

    return result;
}

额外注意点

  • 你原来代码中的db.Add(instance);完全没必要,这会将空实例添加到上下文,属于无效操作,直接删除即可。
  • foreignKey.Properties.First().Name可以拿到外键列的名称,如果需要可以保留,但和导航属性是不同的概念。

内容的提问来源于stack exchange,提问作者Tomáš Sýkora

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:58:28