如何摆脱多个左键在EF核心急切地加载相同桌子

发布于 2025-02-08 13:03:44 字数 1682 浏览 3 评论 0原文

我正在用急切的加载将Oracle SP转换为EFCORE,但我想知道如何更有效地转换以下查询。

我的主要目的是编码它更干净,并学习更好的方法。它导致为.include()创建许多MRC_BATCH_INFO实例,这不是我想要的。

              SELECT C.COLL_ID,
                MI.MRC_INC_NAME,
                ME.MRC_EXC_NAME,
                SI.STR_INC_NAME,
                SE.STR_EXC_NAME,
                AI.MSTR_INC_NAME,
                AE.MSTR_EXC_NAME,
                FROM MERCHANT C
               ,MRC_BATCH_INFO MI
               ,MRC_BATCH_INFO ME
               ,MRC_BATCH_INFO SI
               ,MRC_BATCH_INFO SE
               ,MRC_BATCH_INFO AI
               ,MRC_BATCH_INFO AE
              WHERE C.COLL_ID = PI_COLL_ID
                AND C.MRC_INC_LIST_ID = MI.COLL_MRC_BATCH_ID(+)
                AND C.MRC_EXC_LIST_ID = ME.COLL_MRC_BATCH_ID(+)
                AND C.STR_INC_LIST_ID = SI.COLL_MRC_BATCH_ID(+)
                AND C.STR_EXC_LIST_ID = SE.COLL_MRC_BATCH_ID(+)
                AND C.MSTR_INC_LIST_ID = AI.COLL_MRC_BATCH_ID(+)
                AND C.MSTR_EXC_LIST_ID = AE.COLL_MRC_BATCH_ID(+)

作为


var result = await _mrcRepository
             .Include(x=>x.MrcBatchInfo_MI)  // I want to get rid of these LeftJ
             .Include(x=>x.MrcBatchInfo_ME)  // reduce it as one if it's possible
             .Include(x=>x.MrcBatchInfo_SI)  // or any other optimization
             .Include(x=>x.MrcBatchInfo_SE)
             .Include(x=>x.MrcBatchInfo_AI)
             .Include(x=>x.MrcBatchInfo_AE)
             .Where(x=>x.CollId==collId)
             //.Select( ) in this part and its OK 
             .ToListAsync();

任何评论。

I'm converting Oracle Sp to EFCore with eager loading but I wonder that how to convert below query with more efficiently.

My main aim is code it more clean and learn a better way if it's possible. It's leads to create many MRC_BATCH_INFO instances for .Include() which is not I want.

              SELECT C.COLL_ID,
                MI.MRC_INC_NAME,
                ME.MRC_EXC_NAME,
                SI.STR_INC_NAME,
                SE.STR_EXC_NAME,
                AI.MSTR_INC_NAME,
                AE.MSTR_EXC_NAME,
                FROM MERCHANT C
               ,MRC_BATCH_INFO MI
               ,MRC_BATCH_INFO ME
               ,MRC_BATCH_INFO SI
               ,MRC_BATCH_INFO SE
               ,MRC_BATCH_INFO AI
               ,MRC_BATCH_INFO AE
              WHERE C.COLL_ID = PI_COLL_ID
                AND C.MRC_INC_LIST_ID = MI.COLL_MRC_BATCH_ID(+)
                AND C.MRC_EXC_LIST_ID = ME.COLL_MRC_BATCH_ID(+)
                AND C.STR_INC_LIST_ID = SI.COLL_MRC_BATCH_ID(+)
                AND C.STR_EXC_LIST_ID = SE.COLL_MRC_BATCH_ID(+)
                AND C.MSTR_INC_LIST_ID = AI.COLL_MRC_BATCH_ID(+)
                AND C.MSTR_EXC_LIST_ID = AE.COLL_MRC_BATCH_ID(+)

as


var result = await _mrcRepository
             .Include(x=>x.MrcBatchInfo_MI)  // I want to get rid of these LeftJ
             .Include(x=>x.MrcBatchInfo_ME)  // reduce it as one if it's possible
             .Include(x=>x.MrcBatchInfo_SI)  // or any other optimization
             .Include(x=>x.MrcBatchInfo_SE)
             .Include(x=>x.MrcBatchInfo_AI)
             .Include(x=>x.MrcBatchInfo_AE)
             .Where(x=>x.CollId==collId)
             //.Select( ) in this part and its OK 
             .ToListAsync();

Thx for any comment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

御弟哥哥 2025-02-15 13:03:44

包括选择有不同的目的。 include中导致在查询中,而EF执行连接是不是,而是用于急切地加载相关数据时您想加载整个实体图。 (一个实体及其相关实体)

选择是处理称为投影的概念。在这些情况下,您不一定会返回实体,而是告诉EF使用其实体及其关系来填充所需的输出。

因此,例如,如果您想要的数据是您的方法返回的东西,我们将创建一个Poco dto对象或ViewModel来保存所需的输出数据:

[Serializable]
public class MerchantDTO
{
    public int CollId { get; set; }
    public string MRC_INC_NAME { get; set; }
    public string MRC_EXC_NAME { get; set; }
    public string STR_INC_NAME { get; set; }
    public string STR_EXC_NAME { get; set; }
    public string MSTR_INC_NAME { get; set; }
    public string MSTR_EXC_NAME { get; set; }

}

我们可以从这里构建select> select条款从商人实体图中加载DTO,EF可以通过导航属性来算出相关数据。这样做的优点是,所得的SQL只能从所需的相关表中撤回数据,而不是从商家和相关表中的所有数据。

var result = await _context.Merchants
    .Where(x=>x.CollId==collId)
    .Select(x => new MerchantDTO
    {
        CollId = x.CollId,
        MRC_INC_NAME = x.MrcBatchInfo_MI.Name,
        MRC_EXE_NAME = x.MrcBatchInfo_ME.Name,
        STR_INC_NAME = x.MrcBatchInfo_SI.Name,
        STR_INC_NAME = x.MrcBatchInfo_SE.Name,
        MSTR_INC_NAME = x.MrcBatchInfo_AI.Name,
        MSTR_INC_NAME = x.MrcBatchInfo_AE.Name
    }).ToListAsync();

...使用更合适的命名约定,我猜想了要返回的姓名属性的详细信息。 EF仍然会产生连接和幕后类型,因此不要指望它可以模仿现有的查询,但是在大多数情况下,绩效明智的是EF生成的查询非常好。

可能有一些复杂的情况可以更明确地优化,在这种情况下,选项是将视图和映射实体映射到视图而不是基本表。 (适合复杂的阅读操作)

Include and Select serve different purposes. While Include results in JOIN in the queries, it is not required for EF to perform joins, instead it is used for Eager Loading related data when you want to load an entire entity graph. (An entity and it's related entities)

Select on the other hand is for handling a concept called Projection. In these cases you aren't necessarily returning entities, but rather telling EF to use it's entities and their relations to populate a desired output.

So for example, if the data you want is something that your method would return, we would create a POCO DTO object or ViewModel to hold that desired output data:

[Serializable]
public class MerchantDTO
{
    public int CollId { get; set; }
    public string MRC_INC_NAME { get; set; }
    public string MRC_EXC_NAME { get; set; }
    public string STR_INC_NAME { get; set; }
    public string STR_EXC_NAME { get; set; }
    public string MSTR_INC_NAME { get; set; }
    public string MSTR_EXC_NAME { get; set; }

}

From here we can build a Select clause to load a DTO from the merchant entity graph, and EF can work out the related data via navigation properties. The advantage of this is that the resulting SQL will only pull back the data from the relevant tables that it needs, rather than everything from the Merchant and related tables.

var result = await _context.Merchants
    .Where(x=>x.CollId==collId)
    .Select(x => new MerchantDTO
    {
        CollId = x.CollId,
        MRC_INC_NAME = x.MrcBatchInfo_MI.Name,
        MRC_EXE_NAME = x.MrcBatchInfo_ME.Name,
        STR_INC_NAME = x.MrcBatchInfo_SI.Name,
        STR_INC_NAME = x.MrcBatchInfo_SE.Name,
        MSTR_INC_NAME = x.MrcBatchInfo_AI.Name,
        MSTR_INC_NAME = x.MrcBatchInfo_AE.Name
    }).ToListAsync();

... using more appropriate naming convention and I guessed at the details like Name property to be returned. EF will still generate Joins and such behind the scenes so don't expect it to mimic an existing query, but for the most part performance wise the queries that EF generates are pretty good.

There may be complex cases that can be optimized more explicitly in which case an option is to leverage Views and mapping entities to the view rather than the base tables. (good for complex read operations)

波浪屿的海角声 2025-02-15 13:03:44
AND C.MRC_INC_LIST_ID = MI.COLL_MRC_BATCH_ID(+)
AND C.MRC_EXC_LIST_ID = ME.COLL_MRC_BATCH_ID(+)
AND C.STR_INC_LIST_ID = SI.COLL_MRC_BATCH_ID(+)
AND C.STR_EXC_LIST_ID = SE.COLL_MRC_BATCH_ID(+)
AND C.MSTR_INC_LIST_ID = AI.COLL_MRC_BATCH_ID(+)
AND C.MSTR_EXC_LIST_ID = AE.COLL_MRC_BATCH_ID(+)

就我个人而言,我认为您的数据库设计倒退。

而不是将商人表带有6个外键的表。您需要一个具有FK到商人的表格,以及一个类型列来表示6(或更多)类型。这要么在MRC_BATCH_INFO表上,要么在新的多一对一的联接表上,具体取决于这两个表的相关方式。

AND C.MRC_INC_LIST_ID = MI.COLL_MRC_BATCH_ID(+)
AND C.MRC_EXC_LIST_ID = ME.COLL_MRC_BATCH_ID(+)
AND C.STR_INC_LIST_ID = SI.COLL_MRC_BATCH_ID(+)
AND C.STR_EXC_LIST_ID = SE.COLL_MRC_BATCH_ID(+)
AND C.MSTR_INC_LIST_ID = AI.COLL_MRC_BATCH_ID(+)
AND C.MSTR_EXC_LIST_ID = AE.COLL_MRC_BATCH_ID(+)

Personally, I think your database design is backwards.

Rather than having a MERCHANT table with 6 foreign keys to the same table. You need a table with a FK to MERCHANT, and a type column to represent the 6 (or more) types. This would either be on the MRC_BATCH_INFO table, or on a new many-to-many join table, depending on how these two tables are related.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文