如何在 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.,看看哪一个适合您的情况。
更新:
如果您正在使用延迟加载,请检查您的DbContext
的Constructor
中是否包含以下语句:
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;
延迟加载在 EF 中是一个不错的选择,只要它用在正确的地方,因为对于每个对象,为了获取其关系,EF 都会创建一个到数据库的新连接。 另一方面,Eager Loading (Include()) 在第一个连接中加载列表中的所有相关对象,其中许多您可能不会使用。 根据要获取的对象数量,您应该在延迟加载和急切加载之间进行选择。
【讨论】:
我在我的字段中添加了虚拟,但这并没有改变任何东西 答案已更新。如果它仍然不起作用,请告诉我。 我试过你的解决方案,但无法在 DbContext 中添加配置。无法识别配置 您是否将这些行添加到您的 DbContext 的构造函数中? 我不能,他一直告诉我配置没有解决以上是关于如何在 OneToMany 关系中加载字段?的主要内容,如果未能解决你的问题,请参考以下文章