为了账号安全,请及时绑定邮箱和手机立即绑定

EF Core: LINQ 选择“多对多对多”到“多对多”

EF Core: LINQ 选择“多对多对多”到“多对多”

C#
慕容708150 2022-11-21 22:05:53

我确实有一个表“参考”和一个表“文章”,其中一篇文章引用了其他文章。


我确实有简单的引用,例如:A -> B


查询语句:


select ab.*

from Article a

inner join Reference ab on ab.ArticleFromId = a.Id

inner join Article b on b.Id = ab.ArticleToId

where a.ArticleNo = "1234"

C# 链接:


_context.Reference

   .Where(r => r.ArticleFromNavigation.ArticleNo.Equals("1234"));

我也有参考链,例如:A -> B -> C(假设一条链中最多只有 3 篇文章)


查询语句:


select ab.ArticleFromId, bc.ArticleToId

from Article a

inner join Reference ab on ab.ArticleFromId = a.Id

inner join Article b on b.Id = ab.ArticleToId

inner join Reference bc on bc.ArticleFromId = b.Id

inner join Article c on c.Id = bc.ArticleToId

where a.ArticleNo = "1234"

这在 SQL 中很容易,因为结果只是乘以额外的连接,但我不知道如何在 LINQ 中编写它。


我希望它是这样的(这是行不通的):


_context.Reference

   .Where(r => r.ArticleFromNavigation.ArticleNo.Equals("1234"))

   .Select(r => new Reference

   {

       ArticleFromNavigation = r.ArticleFromNavigation, //this is article "A"

       ArticleToNavigation = r.ArticleToNavigation.ReferenceArticleToNavigations //this wont work as it's a iCollection

   }).AsNoTrackable();

在这里,我想要“A -> C”的“参考”类型的新结果。我想我必须在“新参考”部分之前包含/然后包含/加入/选择/selectmany(?)集合,但我不知道。


有什么办法可以存档吗?


查看完整描述

2 回答

?
慕婉清6462132

TA贡献1502条经验 获得超1个赞

好吧,您可以像在 SQL 中一样完成它,但使用导航属性而不是连接。


我将使用 LINQ 查询语法,因为它能更好地显示相似性,而且方法语法对于此类查询来说非常复杂且难以阅读:


from a in _context.Article

from ab in a.ReferenceArticleFromNavigations

let b = ab.ArticleToNavigation

from bc in b.ReferenceArticleFromNavigations

let c = bc.ArticleToNavigation

where a.ArticleNo = "1234"

select new Reference

{

    ArticleFromNavigation = a,

    ArticleToNavigation = c,

}

这些let语句不是很需要(您可以直接使用引用导航属性),我包含它们只是为了使 LINQ 查询更接近 SQL 查询。


实际上,在这种情况下等效方法并没有那么糟糕 - 使用嵌套将多个级别展平SelectMany并使用重载投影 (top, bottom) 对,SelectMany允许:


_context.Article

    .Where(a => a.ArticleNo = "1234")

    .SelectMany(a => a.ReferenceArticleFromNavigations

        .SelectMany(ab => ab.ArticleToNavigation.ReferenceArticleFromNavigations)

        // include as many `SelectMany` like the above as you wish until you hit the desired level of nesting

        .Select(bc => bc.ArticleToNavigation),

    (a, c) => new Reference

    {

        ArticleFromNavigation = a,

        ArticleToNavigation = c,

    });


查看完整回答
反对 回复 2022-11-21
?
炎炎设计

TA贡献1529条经验 获得超3个赞

我将数据库建模为类以使语法正确。请参阅下面的代码:


using System.Collections.Generic;

using System.Linq;

using System.Text;


namespace ConsoleApplication107

{

    class Program

    {

        static void Main(string[] args)

        {

            Context _context = new Context();

            string ArticleNo = "1234";


            var results = (from a in _context.article.Where(x => x.Id == ArticleNo)

                           join ab in _context.reference

                              .Where(x => (x.ArticleFromId == x.ArticleToId))

                              on a.Id equals ab.ArticleFromId

                           select new { a = a, ab = ab }

                          ).Select(r => new Reference()

                          {

                              ArticleFromNavigation = r.a,

                              ArticleToNavigation = r.a.ReferenceArticleToNavigations.ToList() 

                          }).ToList();

        }

    }


    public class Context

    {

        public List<Reference> reference { get; set; }

        public List<Article> article { get; set; }

    }

    public class Reference

    {

        public string ArticleFromId { get; set; }

        public string ArticleToId { get; set; }

        public Article ArticleFromNavigation { get; set; }

        public List<string> ArticleToNavigation { get; set; }

    }

    public class Article

    {

        public string Id { get; set; }

        public List<string> ReferenceArticleToNavigations { get; set; }

    }


}


查看完整回答
反对 回复 2022-11-21
  • 2 回答
  • 0 关注
  • 6 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信