【问题标题】:Get Object with deep level of related entity获取具有深层相关实体的对象
【发布时间】:2018-12-10 05:15:42
【问题描述】:

假设我有一个具有如下一对一关系的实体类:

public class Transaction
{
    public int TransactionID { get; set; }
    public Double Amount { get; set; }
    public int TransactionDetailID { get; set; }

    public virtual TransactionDetail TransactionDetailFk { get; set; }
}
public class TransactionDetail
{
    public int TransactionDetailID { get; set; }
    public DateTime PostedDate { get; set; }
    public int TransactionTypeID { get; set; }
    public int TransactionCategoryID { get; set; }
    public int PaymentMethodID { get; set; }
    public int PaymentPayorID { get; set; }

    public virtual TransactionType TransactionTypeFk { get; set; }
    public virtual TransactionCategory TransactionCategoryFk { get; set; }
    public virtual PaymentMethod PaymentMethodFk { get; set; }
    public virtual PaymentPayor PaymentPayorFk { get; set; }
    public virtual Transaction TransactionFk { get; set; }
}

现在我想获得一个基于 TransactionID 的 Transaction 对象,此外我想从 Transaction 获取我所有的相关对象到 TransactionDetail to (TransactionType/TransactionCategory/PaymentMethod/PaymentPayor),这是一个两级数据映射,我的函数是这样的:

public async Task<Transaction> GetSingleFullTransactionByIDAsync(int transactionID)
    => await GetSingleOrDefaultAsync(
            predicate: tr => (tr.TransactionID == transactionID),
            include: (obj => (
                            obj
                            .Include(entity => entity.TransactionDetailFk)
                                .ThenInclude(td => td.PaymentPayorFk)
                            .Include(entity => entity.TransactionDetailFk)
                                .ThenInclude(td => td.PaymentMethodFk)
                            .Include(entity => entity.TransactionDetailFk)
                                .ThenInclude(td => td.TransactionTypeFk)
                            .Include(entity => entity.TransactionDetailFk)
                                .ThenInclude(td => td.TransactionCategoryFk)
                    ))
        );

我觉得我的代码不是那么干净整洁,因为对于 Transaction Detail 的每个相关实体,我实际上都包含了多个 transaction detail 实例...我想做类似下面的事情,其中​​只包含一个 Transaction 实例细节但实体框架不允许我这样做:

public async Task<Transaction> GetSingleFullTransactionByIDAsync(int transactionID)
    => await GetSingleOrDefaultAsync(
            predicate: tr => (tr.TransactionID == transactionID),
            include: (obj => (
                            obj
                            .Include(entity => entity.TransactionDetailFk)
                                .ThenInclude(td => td.PaymentPayorFk)
                                .ThenInclude(td => td.PaymentMethodFk)
                                .ThenInclude(td => td.TransactionTypeFk)
                                .ThenInclude(td => td.TransactionCategoryFk)
                    ))
        );

那么,使用 EF 核心执行此操作的有效方法是什么?注意这里我使用的是存储库模式,所以我不能使用 sql-to-linq 表达式,而只需要使用“Include”/“ThenInclude”操作...

【问题讨论】:

    标签: c# entity-framework-core


    【解决方案1】:

    我觉得我的代码不是那么干净整洁,因为对于交易细节的每个相关实体,我实际上都包含了多个交易细节实例......

    这正是在 EF Core 中包含多个相关实体的预期(“设计”)方式。它在 EF Core 文档的Loading Related Data - Including multiple levels 部分中进行了解释(通过示例):

    您可能希望为要包含的实体之一包含多个相关实体。例如,在查询博客时,您包含帖子,然后想要同时包含帖子的作者和标签。为此,您需要指定从根开始的每个包含路径。例如,博客 -> 帖子 -> 作者和博客 -> 帖子 -> 标签。这并不意味着您将获得冗余连接,在大多数情况下,EF 会在生成 SQL 时合并连接。

    注意最后一段。回顾一下,每个Include / ThenInclude 链代表一个要加载的实体path。包含路径中包含的每个实体仅包含一次。

    【讨论】:

    • 非常感谢您的解释和资源分享!
    猜你喜欢
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多