【问题标题】:Recursive Linq query递归 Linq 查询
【发布时间】:2017-08-13 11:32:32
【问题描述】:

目前我正在使用 WebApi 和实体框架,所以我有 3 个实体:产品、类别和产品类别;他们的关系是:

我的问题是 Category 实体有 Category Parent 属性,所以它是递归的,我的 Category Controller 看起来像这样:

public async Task<IHttpActionResult> GetCategory()
        {
            var category = await db.Category.Select(x=>new {
                x.categoryDesc,
                x.CategoryId,
                x.categoryImage,
                x.categoryName,
                x.categoryParent
            }).ToListAsync();
            return Ok(category);
        }

我正在返回一个匿名对象,属性 categoryParent 与 category 相同,因此它是递归的;当我用 Category 表中的模拟数据填充数据库并调用 get 方法时,一切运行正常,因为我没有任何数据 en ProductCategory,但是当我填充它(ProductCategory 表)时,程序崩溃了。 我的实体类是:

public class Category {
    public int CategoryId { set; get; }
    public string categoryName { set; get; }
    public string categoryDesc { set; get; }
    public string categoryImage { set; get; }
    public int? categoryParentId { set; get; }
    public virtual ICollection<ProductCategory> ProductCategories { set; get; }
    public virtual Category categoryParent { set; get; }
}

public class Product{
    public int ProductId { set; get; }
    public string productName { set; get; }
    public string productDesc { set; get; }
    public double productPrice { set; get; }
    public string productUrl { set; get; }
    public DateTime productPublishDate { set; get; }
    public DateTime productModifyDate { set; get; }
    public bool productStatus { set; get; }
    public int productStock { set; get; }
    public virtual ICollection<ProductCategory> ProductCategories { set; get; }    
}
public class ProductCategory : IProductCategory {
    [Required]
    [Key]
    [ForeignKey("Category")]
    [Column(Order = 1)]
    public int CategoryId { set; get; }
    [Required]
    [Key]
    [ForeignKey("Product")]
    [Column(Order = 2)]
    public int ProductId { set; get; }
    public virtual Product Product { set; get; }
    public virtual Category Category { set; get; }
}

你能帮我修复它吗?所以当我返回 categoryParent 时递归返回它,谢谢

【问题讨论】:

  • 你遇到了什么错误?
  • 我得到一个 System.StackOverflowException '因为当程序导航到 ProductCategory 时,它导航到 Product 和 Category 并对无穷大做同样的事情,它是一个无限循环,所以我的问题是我怎么能设置导航,使其不循环但递归返回类别
  • 如果没有一个好的minimal reproducible example 清楚地说明场景,就不可能给你一个实际的答案。但无论答案是什么,它都将采用无限递归代码的all 解决方案的形式:您需要终止递归,一旦达到适当的终止条件就 递归。例如,可能有一点categoryParentnull,或者某个已知的自引用值;此时,您应该返回一些不需要递归的值(例如 null 或已知的自引用值)。

标签: c# entity-framework linq recursion


【解决方案1】:

非常感谢,但我找到了解决方案:https://practiceaspnet.wordpress.com/2015/11/09/many-to-many-relationships-with-additional-fields/

我使用 fluent API 解决了我遇到的导航递归问题:

modelBuilder.Entity<Category>()
.HasMany(x => x.ProductCategories)
.WithRequired(x => x.Category)
.HasForeignKey(x=>x.CategoryId);

modelBuilder.Entity<Product>()
.HasMany(x => x.ProductCategories)
.WithRequired(x => x.Product)
.HasForeignKey(x => x.ProductId);

基本上,WithRequired 方法会阻止关系另一端的导航属性,因此它会停止递归

【讨论】:

    【解决方案2】:

    我猜如果您明确说明您希望如何组织信息并删除虚拟属性,您可能会更幸运

    IQueryable<Category> category = db.Category;
    
    var result = category.Where(w => w.categoryParentId != null)
                         .Join(category,
                               child => (int)child.categoryParentId,
                               parent => parent.CategoryId,
                               (child, parent) => new { 
                                        child.categoryDesc, 
                                        child.CategoryId, 
                                        child.categoryImage, 
                                        child.categoryName, 
                                        parent
                               }         
    );
    
    return Ok(await result.ToListAsync());
    

    这应该会得到与上面查询相同的结果,然后你可以删除:

    public virtual Category categoryParent { set; get; }
    

    【讨论】:

      猜你喜欢
      • 2012-01-29
      • 1970-01-01
      • 1970-01-01
      • 2014-01-25
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多