如何在 OneToMany 关系中加载字段?

Posted

技术标签:

【中文标题】如何在 OneToMany 关系中加载字段?【英文标题】:How to load fields in a OneToMany relation? 【发布时间】:2019-07-19 17:56:17 【问题描述】:

通过 APIController 加载时如何加载 OnetoMany Field。

我有一个文章模型

public class Article : BaseEntity


    public string Title
    
        get; set;
    

    public Edition Edition
    
        get; set;
    


还有一个版本模型

public class Edition : BaseEntity

    public string Title
    
        get; set;
    

    public int Position  get; set; 


BaseEntity 模型如下所示:

public class BaseEntity

    public Guid ID  get; set; 

    [Timestamp]
    public byte[] Timestamp  get; set; 

    public BaseEntity()
    
        ID = Guid.NewGuid();
    

我在我的文章控制器中定义了一个 HttpGet 函数,我想在其中加载我的所有文章。

[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesDefaultResponseType]
public ActionResult<IEnumerable<Article>> GetArticles([FromRoute] Guid editionId)

    return Ok(_context.Articles);

不幸的是,EditionId 没有与其他字段一起加载。这是 JSON 的样子:

[
    
        "title": "Article Postman",
        "edition": null,
        "id": "74b53ba7-75a4-46c6-a70f-470e73c83ee5",
        "timestamp": "AAAAAAAAB+M="
    ,
    
        "title": "Title",
        "edition": null,
        "id": "d74b4ac3-7ddc-4c89-bd74-4fbe3fbe0cd8",
        "timestamp": "AAAAAAAAB+E="
    ,
    
        "title": "Article Postman 2",
        "edition": null,
        "id": "5dddd99f-151a-4325-91f7-c8295b872410",
        "timestamp": "AAAAAAAAB+U="
    
]

【问题讨论】:

@Chayim Friedman,你为什么要删除你的解决方案。它对我有用吗。谢谢 【参考方案1】:

我建议采用 EF Core 提供的简单解决方案,即每次为特定数据调用数据访问层时添加 .Include(x=>x.ReferenceIWantToLoad)。 这避免了在项目模型中进行任何重组以将关键字“virtual”添加到每个外部引用,例如:

var allArticlesWithEditions = await _dbContext.Articles.Include(x=>x.Edition).ToListAsync();

PS:为了能够忽略无限循环的引用,您希望将此添加到启动文件配置中:

services.AddMvc()
        .AddJsonOptions(
            options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );

【讨论】:

谢谢,这就是我使用 Spring Framework 所做的。这种方法很有效。 只加载一篇文章时如何做同样的事情 -> [var article = await _dbContext.Articles.FindAsync(id);]? 完全相同,但不适用于 Find 方法,有一种解决方法,但使用 firstordefaultasync 更简单优雅 _dbContext.Articles.Include(articles=>article.Edition).FirstOrDefaultAsync(x=>x.身份证==身份证);顺便说一句,一周过去了,您应该接受上述答案中的任何一个作为已接受的答案 哦有一个错字...“var article = _dbContext.Articles.Include(articles =>articles.Edition).FirstOrDefaultAsync(x => x.ID == id);”在articles.Edition 上它缺少一个's' 是的,只有在序列中有多个元素时,'single' 方法会抛出异常,但对于您的场景,您的 ID 将始终是唯一的,因此它没有问题。 【参考方案2】:

只需将您的property 虚拟化为Lazy Loading

public virtual Edition Edition

    get; set;

不过,请查看Lazy Loading vs Eager Loading.,看看哪一个适合您的情况。

更新:

如果您正在使用延迟加载,请检查您的DbContextConstructor 中是否包含以下语句:

Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;

延迟加载在 EF 中是一个不错的选择,只要它用在正确的地方,因为对于每个对象,为了获取其关系,EF 都会创建一个到数据库的新连接。 另一方面,Eager Loading (Include()) 在第一个连接中加载列表中的所有相关对象,其中许多您可能不会使用。 根据要获取的对象数量,您应该在延迟加载和急切加载之间进行选择。

【讨论】:

我在我的字段中添加了虚拟,但这并没有改变任何东西 答案已更新。如果它仍然不起作用,请告诉我。 我试过你的解决方案,但无法在 DbContext 中添加配置。无法识别配置 您是否将这些行添加到您的 DbContext 的构造函数中? 我不能,他一直告诉我配置没有解决

以上是关于如何在 OneToMany 关系中加载字段?的主要内容,如果未能解决你的问题,请参考以下文章

你如何在 django 中加载自定义字段

如何在 WKWebView 中加载的页面中的隐藏字段中获取值绑定

如何在 Data Mapper 中加载一对多关系?

如何在Laravel中加载嵌套关系

如何在 Firebase 实时数据库中加载/检索多对多关系

如何忽略在 django admin list_display 中加载巨大的字段?