如何解决如何正确使用 EntityRepository 实例?
文档强调我应该为每个请求使用一个新的 EntityManager
,甚至还有一个中间件可以自动生成它,或者我可以使用 em.fork()
。到目前为止一切顺利。
EntityRepository
是使代码可读的好方法。我在文档中找不到关于它们如何与 EntityManager
实例相关的任何内容。 express-ts-example-app
示例使用存储库的单个实例和 RequestContext
中间件。这表明有一些幕后魔法可以至少使用 EntityManager
找到正确的 RequestContext
实例。真的是这样吗?
另外,如果我手动分叉 EM,它还能找到合适的吗?考虑以下示例:
(async () => {
DI.orm = await MikroORM.init();
DI.em = DI.orm.em;
DI.companyRepository = DI.orm.em.getRepository(Company);
DI.invoiceRepository = DI.orm.em.getRepository(Invoice);
...
fetchInvoices(em.fork());
}
async function fetchInvoices(em) {
for (const company of await DI.companyRepository.findAll()) {
fetchInvoicesOfACompany(company,em.fork())
}
}
async function fetchInvoicesOfACompany(company,em) {
let done = false;
while (!done) {
const invoice = await getNextInvoice(company.taxnumber,company.lastInvoice);
if ( invoice ) {
DI.invoiceRepository.persist(invoice);
company.lastInvoice = invoice.id;
em.flush();
} else {
done = true;
}
}
}
DI.invoiceRepository.persist()
中的 fetchInvoicesOfACompany()
是否使用了正确的 EM 实例?如果没有,我该怎么办?
另外,如果我没记错的话,em.flush()
中的 fetchInvoicesOfACompany()
不会更新公司,因为它属于另一个 EM - 我应该如何处理这样的情况?
解决方法
首先,repository 只是 EM 之上的一个薄层(如果需要,可以是扩展点),它暴露了实体名称,因此您不必将其传递给 EM 方法的第一个参数(例如 { {1}} 对 em.find(Ent,...)
。
然后是上下文 - 每个请求都需要一个专用的上下文,因此它有自己的身份映射。如果您使用 repo.find(...)
帮助程序,上下文将通过 RequestContext
API 创建和保存。多亏了这一点,在域处理程序中执行的所有方法都将自动使用正确的实例 - 这发生在 domain
方法中,该方法首先检查 em.getContext()
助手。
WAL enable-disable is known to have issues
检查测试以更好地了解其工作原理:
https://mikro-orm.io/docs/identity-map/#requestcontext-helper-for-di-containers
因此,如果您使用存储库,使用 RequestContext
助手它会正常工作,因为单例存储库实例将使用单例 EM 实例,然后该实例将通过 RequestContext
使用适当的基于请求的实例。
但是如果您改用手动分叉,则您有责任使用正确的存储库实例 - 每个 EM 分叉都有自己的一个。所以在这种情况下你不能使用单例,你需要做 em.getContext()
。
顺便说一句,如果您在节点 12+ 上,您也可以使用速度更快的 forkedEm.getRepository(Ent)
(并且不会被弃用)。 AsyncLocalStorage
助手实现将在 v5 中使用 ALS,因为将需要节点 12+。
https://github.com/mikro-orm/mikro-orm/blob/master/tests/RequestContext.test.ts
您可以做的另一件事是手动使用 RequestContext
助手而不是通过中间件 - 类似于以下内容:
RequestContext
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。