EfCore 嵌套列表与 DDD 模式中的其他 AggrgateRoot 关系

问题描述 投票:0回答:1

我对 DDD 结构有疑问,我想我不太理解该模式。

我的数据库 ERD: App Orders ERD

简短。 我有三个 AggrgateRoot(AppOrders - AppTests - AppAntibiotics)。 AppOrders 具有嵌套列表 AppOrderItems 链接(一对一)与 AppMicrobiologicalReportResults(每种类型的 Ef 表)每个项目都有三个列表(敏感 - 中度 - 耐药) AppMicrobiologicalReportResults 和 AppAntibiotics 之间的 AppAntibiotics (多对多关系)这里是问题

问题。 如何通过 Ef Core 查询的最佳实践提取此输出而不与 DDD 模式冲突

{
    "sample": "string",
    "pusCells": "string",
    "gramStainedFilms": "string",
    "znStainedFilms": "string",
    "aerobic": "string",
    "viableCount": "Mild growth",
    "mycobacterialCulture": "string",
    "mycologicalCulture": "string",
    "sensitiveItems": [
      {
        "antibioticId": 2,
        "antibioticName": "Amoxicillin" //<== here is my problem
      },
      {
        "antibioticId": 1,
        "antibioticName": "Penicillins" //<== here is my problem
      }
    ],
    "intermediateItems": [],
    "resistantItems": [],
    "testId": "1dfa0d50-4ed8-fb4d-5ed3-3a0f8876cf1e",
    "testName": "Microbiological Report",
    "status": 0,
    "resultDate": null,
    "resultPrinted": false,
    "price": 0,
    "id": "20557835-bcdd-1cb4-ef22-3a0f887707ba"
  }

一些笔记。 1-我使用Abp框架,Netcore 7,SqlLite 2- 这是所有者的操作方法

public async Task<MicrobiologicalReportResultDto> GetMicrobiologicalReport(Guid id,Guid itemId)
    {
        
        var itemsQuery = await _itemsRepository.WithDetailsAsync();
        itemsQuery = itemsQuery.Where(x => x.OrderId == id && x.Id == itemId);

        var testQuery = await _testRepository.GetQueryableAsync();
        
        // This is Antibiotic Query
        var antibioticsQuery = await _antibioticsRepository.GetQueryableAsync();

        var query = 
            from item in itemsQuery 
            join test in testQuery 
                on item.TestId equals test.Id
            select new { item, test};

        var entity = await AsyncExecuter.FirstOrDefaultAsync(query);

        if (entity is null)
        {
            throw new EntityNotFoundException();
        }
        if (entity.item is not MicrobiologicalReportResult)
        {
            throw new BusinessException("Error Types");
        }

        var rc = ObjectMapper.Map<MicrobiologicalReportResult,MicrobiologicalReportResultDto>(
            entity.item.As<MicrobiologicalReportResult>());
        
        rc.TestName = entity.test.Name;

        return rc;
    }

3-这是 ef Fluent api 配置

        builder
            .HasMany(x => x.Sensitive)
            .WithMany()
            .UsingEntity<MicrobiologicalAntibiotic>("MicrobiologicalReportSensitiveAntibiotics",
                l=>l.HasOne<Antibiotic>()
                    .WithMany()
                    .HasForeignKey(c=>c.AntibioticId),
                r=>r.HasOne<MicrobiologicalReportResult>()
                    .WithMany(x=>x.SensitiveItems)
                    .HasForeignKey(c=>c.OrderItemId));

// Others Removed for lack of complexity

4-这是我写来测试的Sql

select * from AppOrderItems itemsQuery
left outer join AppTests testsQuery
on testsQuery.Id = itemsQuery.TestId
left outer join MicrobiologicalReportSensitiveAntibiotics sens
on sens.OrderItemId = itemsQuery.Id
left outer join AppAntibiotics antbiotic 
on sens.AntibioticId = antbiotic.Id

如果有不清楚的地方,我深表歉意。

非常感谢你。

我尝试了 linq group into 但它很困惑,因为它需要子列表 Queryables

c# .net-core entity-framework-core domain-driven-design
1个回答
0
投票

如果我理解正确,我认为你的问题中有两件事需要考虑:

  1. 您的查询跨越多个聚合。你应该把它放在一种方法中吗?或者您应该将其分成多个部分并在客户端代码中收集结果(就像您在问题中所做的那样)?如果放在一个方法里,那么查询方法放在哪里呢?哪个存储库应该定义它?如果您的性能不佳,我认为您应该将其作为优化查询的一种方法,一个好的解决方案可能是为此查询使用新的结构存储库。
  2. 您要对查询结果做什么?是为了报告还是对结果进行操作并修改?如果它是只读的,您应该考虑CQS。 CQS(或 CQRS,如果您可以拆分写入和读取数据库)与 DDD 配合良好。 DDD 重点关注写入模型。检查不变量是为了修改数据(CQS 中的命令),而不是读取数据。如果您不熟悉 CQS,它表示您应该将命令(修改数据的请求)与查询(不修改任何数据的请求,称为只读查询)分开。通过这种方式,您可以实现关注点分离,并且可以更有效地专注于问题。指定另一个模型用于只读目的可以帮助您优化查询模型。从这个意义上说,这些查询不会污染您的存储库。在读取模型上,您可以将另一个 DbContext 定义为只读,甚至可以为聚合根定义导航属性以相互引用。重点是它不会修改数据,所以不需要担心不变量。
© www.soinside.com 2019 - 2024. All rights reserved.