使用 EF Core 在通用存储库中包含使用反射的所有导航属性 [英] Include all navigation properties using Reflection in generic repository using EF Core

查看:25
本文介绍了使用 EF Core 在通用存储库中包含使用反射的所有导航属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 EF Core 项目创建通用存储库,以避免必须为所有模型编写 CRUD.我遇到的一个主要障碍是未加载导航属性,因为 Core 尚不支持延迟加载,并且泛型类显然无法定义 .Include 类特定属性的语句.

I'm working on creating a generic repository for an EF Core project to avoid having to write CRUD for all models. A major roadblock I've hit is navigation properties not being loaded since Core doesn't yet support lazy loading and the generic class obviously can't define .Include statements for class specific properties.

我正在尝试为我的 Get 方法执行类似的操作以动态包含所有属性:

I'm trying to do something like this for my Get method to include all the properties dynamically:

public virtual T Get(Guid itemId, bool eager = false)
        {
            IQueryable<T> querySet = _context.Set<T>();

            if (eager)
            {
                foreach (PropertyInfo p in typeof(T).GetProperties())
                {
                    querySet = querySet.Include(p.Name);
                } 
            }

            return querySet.SingleOrDefault(i => i.EntityId == itemId);
        }

但是当包含不是导航属性的属性时会引发错误.

But it throws an error when including properties that are not navigation properties.

我发现这个答案大致相同,但它适用于 EF 5,并且涉及 EF 核心中不存在的方法:

I found this answer which is about the same thing but its for EF 5 and involves methods that are not present in EF core:

EF5 如何获取列表域对象的导航属性

是否可以在 EF Core 中完成同样的事情?

Is it possible to accomplish the same thing in EF Core?

推荐答案

与以前的 EF 版本相比,在 EF Core 中使用元数据要容易得多.DbContext类提供 Model 提供访问权限的属性

Working with metadata in EF Core is much easier than in previous EF versions. The DbContext class provides Model property which provides access to

关于实体形状、它们之间的关系以及它们如何映射到数据库的元数据.

The metadata about the shape of entities, the relationships between them, and how they map to the database.

执行您要求的代码可能是这样的:

The code which does what you ask could be like this:

public virtual IQueryable<T> Query(bool eager = false)
{
    var query = _context.Set<T>().AsQueryable();
    if (eager)
    {
        var navigations = _context.Model.FindEntityType(typeof(T))
            .GetDerivedTypesInclusive()
            .SelectMany(type => type.GetNavigations())
            .Distinct();

        foreach (var property in navigations)
            query = query.Include(property.Name);
    }
    return query;
}

public virtual T Get(Guid itemId, bool eager = false)
{
    return Query(eager).SingleOrDefault(i => i.EntityId == itemId);
}

请注意,虽然这可以满足您的要求,但它是一种非常有限的通用方法,因为它仅急切加载实体的直接导航属性,即不使用 ThenInclude 处理加载嵌套导航属性.

Please note that although this does what you asked for, it's quite limited generic approach since it eager loads only the direct navigation properties of the entity, i.e. does not handle loading nested navigation properties with ThenInclude.

这篇关于使用 EF Core 在通用存储库中包含使用反射的所有导航属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆