如何在泛型类型中使用 linq 包含函数

Posted

技术标签:

【中文标题】如何在泛型类型中使用 linq 包含函数【英文标题】:How to use linq include function in generic type 【发布时间】:2021-11-26 08:08:12 【问题描述】:

我想找一个员工并为这个用户获得许多项目。如何在我的查询中使用包含函数 _dbContext.Set ().FindAsync(id)

【问题讨论】:

您的问题应该包含Minimal, Reproducible Example 这能回答你的问题吗? What does Include() do in LINQ? 你做了类似context.Employees.Find(id).Include(e => e.Projects) 【参考方案1】:

我认为这将是您正在寻找的。我相当详尽地尝试将通用表示法与反射包含一起使用,但发现它很困难。 因此,FullFindAsync 方法将采用 Type 对象,您可以使用它来代替 T。然后是 param objects[] 用作搜索的关键

public static async Task<object> FullFindAsync(this DbContext context, Type entityType, params object[] keyValues)

    object entity = null;

    //handle an Interface as a passed in type
    if (entityType.IsInterface)
    
        //get all Types of Models in the DbContext that implement the Interface
        var implementedModels = context.Model.GetEntityTypes()
                                    .Select(et => et.ClrType)
                                        .Where(t => entityType.IsAssignableFrom(t))
                                            .ToList();

        //loop through all Models and try to find the object via the parameters
        foreach (var modelType in implementedModels)
         //TODO: it would be nice to not have to do a find on every Model, but only optimize if this has performance hits
            entity = await context.FindAsync(modelType, keyValues);
            if (entity != null) break;
        
    
    else
        //find the object, via regular Find
        entity = await context.FindAsync(entityType, keyValues);

    //didnt find the object
    if (entity == null) return null;

    //loop through all navigation properties
    foreach (var navigation in entity.GetType().GetProperties())
    
        //skip NotMapped properties (to avoid context collection error)
        if (context.Entry(entity).Metadata.FindNavigation(navigation.Name) == null)
            continue;

        //check and load reference and collection properties
        if (typeof(IMyRootType).IsAssignableFrom(navigation.PropertyType))
            context.Entry(entity).Reference(navigation.Name).Load();
        if (typeof(IEnumerable<object>).IsAssignableFrom(navigation.PropertyType))
            context.Entry(entity).Collection(navigation.Name).Load();
    

    return entity;

然后你可以像这样使用它: var myItem = await dbContext.FullFindAsync(typeof(T), someId);

我所做的是让上下文中的每个类都实现一个包含唯一键的简单接口。因此,您可能需要修改该方法以满足您的需求,但希望它可以提供帮助。 请注意,这在大型数据集上可能效率很低,因此请谨慎使用。

【讨论】:

以上是关于如何在泛型类型中使用 linq 包含函数的主要内容,如果未能解决你的问题,请参考以下文章

涉及泛型对象的泛型属性的赋值无法在泛型函数中正确进行类型检查

如何在泛型集合上创建扩展方法

通过在运行时在泛型方法中进行类型转换来使用递归函数

如何添加类型约束以在泛型方法中包含任何可序列化的内容?

在泛型方法中返回原始集合类型

C# 在泛型中重复使用类型时缩短语法?