【问题标题】:DbSet include extension method loopingDbSet 包含扩展方法循环
【发布时间】:2017-02-20 12:06:26
【问题描述】:

我添加了以下扩展方法

    /// <summary>
    /// Provides a statically typed interface for db includes
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="set">The set.</param>
    /// <param name="includes">The includes.</param>
    /// <returns>DbSet&lt;T&gt;.</returns>
    public static DbSet<T> Include<T>(this DbSet<T> set, params Expression<Func<T, object>>[] includes) where T : class
    {
        if (includes != null)
        {
            foreach (var expression in includes)
            {
                set.Include(expression);
            }
        }
        return set;
    }

这是基于我在这里找到的存储库代码

https://github.com/carbonrobot/FullStackEF/tree/master/src

但是,当我将其与以下内容一起使用时

    public ServiceResponse<Town> Get(int id)
    {
        Func<Patient> func = delegate
        {
            using (var context = _contextFactory())
            {
                return context.Get<Town>(id, x => x.County);
            }
        };
        return this.Execute(func);
    }

其中城镇类包含县实体。

当它调用扩展方法而不是基础包含时,我得到了一个无限循环?

有什么想法我在这里做错了吗?

【问题讨论】:

    标签: linq entity-framework-5 linq-to-objects c#-5.0


    【解决方案1】:

    那个方法有几个错误。

    DbExtensions.Include 方法具有以下签名:

    public static IQueryable<T> Include<T, TProperty>(
        this IQueryable<T> source,
        Expression<Func<T, TProperty>> path
    )
    where T : class
    

    如您所见,它接收IQueryable&lt;T&gt; 并返回另一个IQueryable&lt;T&gt;,该IQueryable&lt;T&gt; 必须分配给一个变量并返回而不是原始值才能生效,代码没有这样做。

    此外,由于该方法在DbSet&lt;T&gt; 类型的set 变量上调用Include,这比IQueryable&lt;T&gt; 更具体,并且参数与自定义方法的签名匹配,编译器只需调用相同的方法,因此是StackOverflowException

    话虽如此,下面是正确的自定义方法签名和实现:

    public static IQueryable<T> Include<T>(this DbSet<T> set, params Expression<Func<T, object>>[] includes)
        where T : class
    {
        var result = set.AsQueryable();
        if (includes != null)
        {
            foreach (var expression in includes)
            {
                result = result.Include(expression);
            }
        }
        return result;
    }
    

    【讨论】:

    • 感谢您的详细解释。一个问题是,因为 repo 使用返回的 DbSet 来链接方法。即 .include(includes).find(id) 因为扩展方法是 return IQueryable (与 DbSet 相反,我失去了链接的能力?有什么想法吗?
    • 嗯,这听起来无法解决,但Include 无论如何都不能与Find 一起工作,所以我想与Find 链接是没有意义的。不过,常规的 LINQ 链应该可以工作。理由是Include 的结果不再是DbSet
    • 好的,很好。所以基本上你会推荐简单的 .include(includes).select(x => x.Id == id); (关于 find 示例)。过滤可查询的结果?
    • 类似的东西 - 准确地说 - .Include(includes).FirstOrDefault(x =&gt; x.Id == id);
    猜你喜欢
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多