EFCore LINQ to SQL запрос медленный при использовании одного запроса - PullRequest
0 голосов
/ 24 октября 2018

При использовании Microsoft.EntityFrameworkCore 2.1.4 в консольном приложении для извлечения данных для XmlSerialization я обнаружил, что следующий запрос LINQ очень медленный и занимает почти 7 минут:

var fullSubmission = context.CYP000
    .Include(p => p.CYP001)
        .ThenInclude(p => p.CYP002)
    .Include(p => p.CYP001)
        .ThenInclude(p => p.CYP101)
            .ThenInclude(r => r.CYP201)
                .ThenInclude(c => c.CYP202)
    .Single(x => x.SubmissionId == submissionId);

24/10/2018 14:50:37 - Retrieved full submission in 00:06:46.8583712

Тогда как если я это сделаюэто в два шага, чтобы получить эквивалентный результат, общее время составляет менее 30 секунд:

var submission = context.CYP000
    .Single(s => s.SubmissionId == submissionId);

var patients = context.CYP001
    .Include(p => p.CYP101)
        .ThenInclude(r => r.CYP201)
            .ThenInclude(c => c.CYP202)
    .Include(p => p.CYP002)
    .Where(p => p.SubmissionId == submissionId)
    .ToList();

submission.CYP001 = patients;

24/10/2018 14:43:29 - Retrieved submission in 00:00:01.1036359
24/10/2018 14:43:50 - Retrieved patients in 00:00:21.0496461

Я не обнаружил никаких проблем с моим DbContext или классами, и в базе данных достаточно индексов, так что вызываетмедленное выполнение?

Это журнал при использовании одного запроса LINQ:

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (12ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT TOP(2) [p].[SubmissionId], [p].[C000010], [p].[C000020], [p].[C000030], [p].[C000040], [p].[C000050], [p].[C000060]

      FROM [CYP000] AS [p]

      WHERE [p].[SubmissionId] = @__submissionId_0

      ORDER BY [p].[SubmissionId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (15ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP001].[SubmissionId], [p.CYP001].[PatientId], [p.CYP001].[C001010], [p.CYP001].[C001020], [p.CYP001].[C001030], [p.CYP001].[C001040], [p.CYP001].[C001050], [p.CYP001].[C001060], [p.CYP001].[C001070], [p.CYP001].[C001080], [p.CYP001].[C001090], [p.CYP001].[C001100], [p.CYP001].[C001110], [p.CYP001].[C001120], [p.CYP001].[C001130], [p.CYP001].[C001140], [p.CYP001].[C001150], [p.CYP001].[C001160], [p.CYP001].[C001170], [p.CYP001].[C001180], [p.CYP001].[C001190], [p.CYP001].[C001200], [p.CYP001].[C001210], [p.CYP001].[C001220], [p.CYP001].[C001230], [p.CYP001].[C001240], [p.CYP001].[C001901]

      FROM [CYP001] AS [p.CYP001]

      INNER JOIN (

          SELECT TOP(1) [p0].[SubmissionId]

          FROM [CYP000] AS [p0]

          WHERE [p0].[SubmissionId] = @__submissionId_0

          ORDER BY [p0].[SubmissionId]

      ) AS [t] ON [p.CYP001].[SubmissionId] = [t].[SubmissionId]

      ORDER BY [t].[SubmissionId], [p.CYP001].[SubmissionId], [p.CYP001].[PatientId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (14ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP001.CYP002].[SubmissionId], [p.CYP001.CYP002].[PatientId], [p.CYP001.CYP002].[C002020], [p.CYP001.CYP002].[C002010], [p.CYP001.CYP002].[C002030], [p.CYP001.CYP002].[C002040], [p.CYP001.CYP002].[C002901]

      FROM [CYP002] AS [p.CYP001.CYP002]

      INNER JOIN (

          SELECT DISTINCT [p.CYP0010].[SubmissionId], [p.CYP0010].[PatientId], [t0].[SubmissionId] AS [SubmissionId0]

          FROM [CYP001] AS [p.CYP0010]

          INNER JOIN (

              SELECT TOP(1) [p1].[SubmissionId]

              FROM [CYP000] AS [p1]

              WHERE [p1].[SubmissionId] = @__submissionId_0

              ORDER BY [p1].[SubmissionId]

          ) AS [t0] ON [p.CYP0010].[SubmissionId] = [t0].[SubmissionId]

      ) AS [t1] ON ([p.CYP001.CYP002].[SubmissionId] = [t1].[SubmissionId]) AND ([p.CYP001.CYP002].[PatientId] = [t1].[PatientId])

      ORDER BY [t1].[SubmissionId0], [t1].[SubmissionId], [t1].[PatientId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (184ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP001.CYP101].[SubmissionId], [p.CYP001.CYP101].[ReferralId], [p.CYP001.CYP101].[C101010], [p.CYP001.CYP101].[C101020], [p.CYP001.CYP101].[C101030], [p.CYP001.CYP101].[C101040], [p.CYP001.CYP101].[C101050], [p.CYP001.CYP101].[C101060], [p.CYP001.CYP101].[C101070], [p.CYP001.CYP101].[C101080], [p.CYP001.CYP101].[C101090], [p.CYP001.CYP101].[C101901], [p.CYP001.CYP101].[C101902], [p.CYP001.CYP101].[C101912], [p.CYP001.CYP101].[PatientId]

      FROM [CYP101] AS [p.CYP001.CYP101]

      INNER JOIN (

          SELECT DISTINCT [p.CYP0011].[SubmissionId], [p.CYP0011].[PatientId], [t2].[SubmissionId] AS [SubmissionId0]

          FROM [CYP001] AS [p.CYP0011]

          INNER JOIN (

              SELECT TOP(1) [p2].[SubmissionId]

              FROM [CYP000] AS [p2]

              WHERE [p2].[SubmissionId] = @__submissionId_0

              ORDER BY [p2].[SubmissionId]

          ) AS [t2] ON [p.CYP0011].[SubmissionId] = [t2].[SubmissionId]

      ) AS [t3] ON ([p.CYP001.CYP101].[SubmissionId] = [t3].[SubmissionId]) AND ([p.CYP001.CYP101].[PatientId] = [t3].[PatientId])

      ORDER BY [t3].[SubmissionId0], [t3].[SubmissionId], [t3].[PatientId], [p.CYP001.CYP101].[SubmissionId], [p.CYP001.CYP101].[ReferralId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (151ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP001.CYP101.CYP201].[SubmissionId], [p.CYP001.CYP101.CYP201].[ContactId], [p.CYP001.CYP101.CYP201].[C201010], [p.CYP001.CYP101.CYP201].[C201020], [p.CYP001.CYP101.CYP201].[C201030], [p.CYP001.CYP101.CYP201].[C201040], [p.CYP001.CYP101.CYP201].[C201050], [p.CYP001.CYP101.CYP201].[C201060], [p.CYP001.CYP101.CYP201].[C201070], [p.CYP001.CYP101.CYP201].[C201080], [p.CYP001.CYP101.CYP201].[C201090], [p.CYP001.CYP101.CYP201].[C201100], [p.CYP001.CYP101.CYP201].[C201110], [p.CYP001.CYP101.CYP201].[C201120], [p.CYP001.CYP101.CYP201].[C201130], [p.CYP001.CYP101.CYP201].[C201140], [p.CYP001.CYP101.CYP201].[C201150], [p.CYP001.CYP101.CYP201].[C201160], [p.CYP001.CYP101.CYP201].[C201902], [p.CYP001.CYP101.CYP201].[C201903], [p.CYP001.CYP101.CYP201].[C201906], [p.CYP001.CYP101.CYP201].[C201909], [p.CYP001.CYP101.CYP201].[C201912], [p.CYP001.CYP101.CYP201].[ReferralId]

      FROM [CYP201] AS [p.CYP001.CYP101.CYP201]

      INNER JOIN (

          SELECT DISTINCT [p.CYP001.CYP1010].[SubmissionId], [p.CYP001.CYP1010].[ReferralId], [t5].[SubmissionId0], [t5].[SubmissionId] AS [SubmissionId1], [t5].[PatientId]

          FROM [CYP101] AS [p.CYP001.CYP1010]

          INNER JOIN (

              SELECT DISTINCT [p.CYP0012].[SubmissionId], [p.CYP0012].[PatientId], [t4].[SubmissionId] AS [SubmissionId0]

              FROM [CYP001] AS [p.CYP0012]

              INNER JOIN (

                  SELECT TOP(1) [p3].[SubmissionId]

                  FROM [CYP000] AS [p3]

                  WHERE [p3].[SubmissionId] = @__submissionId_0

                  ORDER BY [p3].[SubmissionId]

              ) AS [t4] ON [p.CYP0012].[SubmissionId] = [t4].[SubmissionId]

          ) AS [t5] ON ([p.CYP001.CYP1010].[SubmissionId] = [t5].[SubmissionId]) AND ([p.CYP001.CYP1010].[PatientId] = [t5].[PatientId])

      ) AS [t6] ON ([p.CYP001.CYP101.CYP201].[SubmissionId] = [t6].[SubmissionId]) AND ([p.CYP001.CYP101.CYP201].[ReferralId] = [t6].[ReferralId])

      ORDER BY [t6].[SubmissionId0], [t6].[SubmissionId1], [t6].[PatientId], [t6].[SubmissionId], [t6].[ReferralId], [p.CYP001.CYP101.CYP201].[SubmissionId], [p.CYP001.CYP101.CYP201].[ContactId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (210ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP001.CYP101.CYP201.CYP202].[SubmissionId], [p.CYP001.CYP101.CYP201.CYP202].[ContactActivityId], [p.CYP001.CYP101.CYP201.CYP202].[C202010], [p.CYP001.CYP101.CYP201.CYP202].[C202020], [p.CYP001.CYP101.CYP201.CYP202].[C202030], [p.CYP001.CYP101.CYP201.CYP202].[C202040], [p.CYP001.CYP101.CYP201.CYP202].[C202050], [p.CYP001.CYP101.CYP201.CYP202].[C202060], [p.CYP001.CYP101.CYP201.CYP202].[C202070], [p.CYP001.CYP101.CYP201.CYP202].[C202080], [p.CYP001.CYP101.CYP201.CYP202].[C202090], [p.CYP001.CYP101.CYP201.CYP202].[C202100], [p.CYP001.CYP101.CYP201.CYP202].[C202110], [p.CYP001.CYP101.CYP201.CYP202].[C202903], [p.CYP001.CYP101.CYP201.CYP202].[C202904], [p.CYP001.CYP101.CYP201.CYP202].[ContactId]

      FROM [CYP202] AS [p.CYP001.CYP101.CYP201.CYP202]

      INNER JOIN (

          SELECT DISTINCT [p.CYP001.CYP101.CYP2010].[SubmissionId], [p.CYP001.CYP101.CYP2010].[ContactId], [t9].[SubmissionId0], [t9].[SubmissionId1], [t9].[PatientId], [t9].[SubmissionId] AS [SubmissionId2], [t9].[ReferralId]

          FROM [CYP201] AS [p.CYP001.CYP101.CYP2010]

          INNER JOIN (

              SELECT DISTINCT [p.CYP001.CYP1011].[SubmissionId], [p.CYP001.CYP1011].[ReferralId], [t8].[SubmissionId0], [t8].[SubmissionId] AS [SubmissionId1], [t8].[PatientId]

              FROM [CYP101] AS [p.CYP001.CYP1011]

              INNER JOIN (

                  SELECT DISTINCT [p.CYP0013].[SubmissionId], [p.CYP0013].[PatientId], [t7].[SubmissionId] AS [SubmissionId0]

                  FROM [CYP001] AS [p.CYP0013]

                  INNER JOIN (

                      SELECT TOP(1) [p4].[SubmissionId]

                      FROM [CYP000] AS [p4]

                      WHERE [p4].[SubmissionId] = @__submissionId_0

                      ORDER BY [p4].[SubmissionId]

                  ) AS [t7] ON [p.CYP0013].[SubmissionId] = [t7].[SubmissionId]

              ) AS [t8] ON ([p.CYP001.CYP1011].[SubmissionId] = [t8].[SubmissionId]) AND ([p.CYP001.CYP1011].[PatientId] = [t8].[PatientId])

          ) AS [t9] ON ([p.CYP001.CYP101.CYP2010].[SubmissionId] = [t9].[SubmissionId]) AND ([p.CYP001.CYP101.CYP2010].[ReferralId] = [t9].[ReferralId])

      ) AS [t10] ON ([p.CYP001.CYP101.CYP201.CYP202].[SubmissionId] = [t10].[SubmissionId]) AND ([p.CYP001.CYP101.CYP201.CYP202].[ContactId] = [t10].[ContactId])

      ORDER BY [t10].[SubmissionId0], [t10].[SubmissionId1], [t10].[PatientId], [t10].[SubmissionId2], [t10].[ReferralId], [t10].[SubmissionId], [t10].[ContactId]

24/10/2018 15:43:44 - Retrieved full submission in 00:06:50.1565598

Это журнал при получении данных в 2 этапа:

warn: Microsoft.EntityFrameworkCore.Model.Validation[30000]

      No type was specified for the decimal column 'C000010' on entity type 'CYP000'. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values using 'ForHasColumnType()'.

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]

      Entity Framework Core 2.1.4-rtm-31024 initialized 'AppDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None

24/10/2018 15:36:34 - Getting data

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (82ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT TOP(2) [s].[SubmissionId], [s].[C000010], [s].[C000020], [s].[C000030], [s].[C000040], [s].[C000050], [s].[C000060]

      FROM [CYP000] AS [s]

      WHERE [s].[SubmissionId] = @__submissionId_0

24/10/2018 15:36:35 - Retrieved submission in 00:00:00.8605259

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (17ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p].[SubmissionId], [p].[PatientId], [p].[C001010], [p].[C001020], [p].[C001030], [p].[C001040], [p].[C001050], [p].[C001060], [p].[C001070], [p].[C001080], [p].[C001090], [p].[C001100], [p].[C001110], [p].[C001120], [p].[C001130], [p].[C001140], [p].[C001150], [p].[C001160], [p].[C001170], [p].[C001180], [p].[C001190], [p].[C001200], [p].[C001210], [p].[C001220], [p].[C001230], [p].[C001240], [p].[C001901]

      FROM [CYP001] AS [p]

      WHERE [p].[SubmissionId] = @__submissionId_0

      ORDER BY [p].[SubmissionId], [p].[PatientId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (175ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP101].[SubmissionId], [p.CYP101].[ReferralId], [p.CYP101].[C101010], [p.CYP101].[C101020], [p.CYP101].[C101030], [p.CYP101].[C101040], [p.CYP101].[C101050], [p.CYP101].[C101060], [p.CYP101].[C101070], [p.CYP101].[C101080], [p.CYP101].[C101090], [p.CYP101].[C101901], [p.CYP101].[C101902], [p.CYP101].[C101912], [p.CYP101].[PatientId]

      FROM [CYP101] AS [p.CYP101]

      INNER JOIN (

          SELECT [p0].[SubmissionId], [p0].[PatientId]

          FROM [CYP001] AS [p0]

          WHERE [p0].[SubmissionId] = @__submissionId_0

      ) AS [t] ON ([p.CYP101].[SubmissionId] = [t].[SubmissionId]) AND ([p.CYP101].[PatientId] = [t].[PatientId])

      ORDER BY [t].[SubmissionId], [t].[PatientId], [p.CYP101].[SubmissionId], [p.CYP101].[ReferralId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (149ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP101.CYP201].[SubmissionId], [p.CYP101.CYP201].[ContactId], [p.CYP101.CYP201].[C201010], [p.CYP101.CYP201].[C201020], [p.CYP101.CYP201].[C201030], [p.CYP101.CYP201].[C201040], [p.CYP101.CYP201].[C201050], [p.CYP101.CYP201].[C201060], [p.CYP101.CYP201].[C201070], [p.CYP101.CYP201].[C201080], [p.CYP101.CYP201].[C201090], [p.CYP101.CYP201].[C201100], [p.CYP101.CYP201].[C201110], [p.CYP101.CYP201].[C201120], [p.CYP101.CYP201].[C201130], [p.CYP101.CYP201].[C201140], [p.CYP101.CYP201].[C201150], [p.CYP101.CYP201].[C201160], [p.CYP101.CYP201].[C201902], [p.CYP101.CYP201].[C201903], [p.CYP101.CYP201].[C201906], [p.CYP101.CYP201].[C201909], [p.CYP101.CYP201].[C201912], [p.CYP101.CYP201].[ReferralId]

      FROM [CYP201] AS [p.CYP101.CYP201]

      INNER JOIN (

          SELECT DISTINCT [p.CYP1010].[SubmissionId], [p.CYP1010].[ReferralId], [t0].[SubmissionId] AS [SubmissionId0], [t0].[PatientId]

          FROM [CYP101] AS [p.CYP1010]

          INNER JOIN (

              SELECT [p1].[SubmissionId], [p1].[PatientId]

              FROM [CYP001] AS [p1]

              WHERE [p1].[SubmissionId] = @__submissionId_0

          ) AS [t0] ON ([p.CYP1010].[SubmissionId] = [t0].[SubmissionId]) AND ([p.CYP1010].[PatientId] = [t0].[PatientId])

      ) AS [t1] ON ([p.CYP101.CYP201].[SubmissionId] = [t1].[SubmissionId]) AND ([p.CYP101.CYP201].[ReferralId] = [t1].[ReferralId])

      ORDER BY [t1].[SubmissionId0], [t1].[PatientId], [t1].[SubmissionId], [t1].[ReferralId], [p.CYP101.CYP201].[SubmissionId], [p.CYP101.CYP201].[ContactId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (190ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP101.CYP201.CYP202].[SubmissionId], [p.CYP101.CYP201.CYP202].[ContactActivityId], [p.CYP101.CYP201.CYP202].[C202010], [p.CYP101.CYP201.CYP202].[C202020], [p.CYP101.CYP201.CYP202].[C202030], [p.CYP101.CYP201.CYP202].[C202040], [p.CYP101.CYP201.CYP202].[C202050], [p.CYP101.CYP201.CYP202].[C202060], [p.CYP101.CYP201.CYP202].[C202070], [p.CYP101.CYP201.CYP202].[C202080], [p.CYP101.CYP201.CYP202].[C202090], [p.CYP101.CYP201.CYP202].[C202100], [p.CYP101.CYP201.CYP202].[C202110], [p.CYP101.CYP201.CYP202].[C202903], [p.CYP101.CYP201.CYP202].[C202904], [p.CYP101.CYP201.CYP202].[ContactId]

      FROM [CYP202] AS [p.CYP101.CYP201.CYP202]

      INNER JOIN (

          SELECT DISTINCT [p.CYP101.CYP2010].[SubmissionId], [p.CYP101.CYP2010].[ContactId], [t3].[SubmissionId0], [t3].[PatientId], [t3].[SubmissionId] AS [SubmissionId1], [t3].[ReferralId]

          FROM [CYP201] AS [p.CYP101.CYP2010]

          INNER JOIN (

              SELECT DISTINCT [p.CYP1011].[SubmissionId], [p.CYP1011].[ReferralId], [t2].[SubmissionId] AS [SubmissionId0], [t2].[PatientId]

              FROM [CYP101] AS [p.CYP1011]

              INNER JOIN (

                  SELECT [p2].[SubmissionId], [p2].[PatientId]

                  FROM [CYP001] AS [p2]

                  WHERE [p2].[SubmissionId] = @__submissionId_0

              ) AS [t2] ON ([p.CYP1011].[SubmissionId] = [t2].[SubmissionId]) AND ([p.CYP1011].[PatientId] = [t2].[PatientId])

          ) AS [t3] ON ([p.CYP101.CYP2010].[SubmissionId] = [t3].[SubmissionId]) AND ([p.CYP101.CYP2010].[ReferralId] = [t3].[ReferralId])

      ) AS [t4] ON ([p.CYP101.CYP201.CYP202].[SubmissionId] = [t4].[SubmissionId]) AND ([p.CYP101.CYP201.CYP202].[ContactId] = [t4].[ContactId])

      ORDER BY [t4].[SubmissionId0], [t4].[PatientId], [t4].[SubmissionId1], [t4].[ReferralId], [t4].[SubmissionId], [t4].[ContactId]

info: Microsoft.EntityFrameworkCore.Database.Command[20101]

      Executed DbCommand (14ms) [Parameters=[@__submissionId_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']

      SELECT [p.CYP002].[SubmissionId], [p.CYP002].[PatientId], [p.CYP002].[C002020], [p.CYP002].[C002010], [p.CYP002].[C002030], [p.CYP002].[C002040], [p.CYP002].[C002901]

      FROM [CYP002] AS [p.CYP002]

      INNER JOIN (

          SELECT [p3].[SubmissionId], [p3].[PatientId]

          FROM [CYP001] AS [p3]

          WHERE [p3].[SubmissionId] = @__submissionId_0

      ) AS [t5] ON ([p.CYP002].[SubmissionId] = [t5].[SubmissionId]) AND ([p.CYP002].[PatientId] = [t5].[PatientId])

      ORDER BY [t5].[SubmissionId], [t5].[PatientId]

24/10/2018 15:36:53 - Retrieved patients in 00:00:18.1113376

Классы

public class CYP000
{
    [XmlIgnore]
    public int SubmissionId { get; set; }

    // CYP000 Properties

    [XmlElement("CYP001")]
    public List<CYP001> CYP001 { get; set; }
}

public class CYP001
{
    [XmlIgnore]
    public int SubmissionId { get; set; }

    [XmlIgnore]
    public long PatientId { get; set; }

    // CYP001 Properties

    [XmlIgnore]
    public CYP000 CYP000 { get; set; }

    [XmlElement("CYP101")]
    public List<CYP101> CYP101 { get; set; }

    [XmlElement("CYP002")]
    public List<CYP002> CYP002 {get;set;}
}

public class CYP002
{
    [XmlIgnore]
    public int SubmissionId { get; set; }
    [XmlIgnore]
    public long PatientId { get; set; }

    // CYP002 Properties

    [XmlIgnore]
    public CYP001 CYP001 { get; set; }
}

public class CYP101
{
    [XmlIgnore]
    public int SubmissionId { get; set; }
    [XmlIgnore]
    public long ReferralId { get; set; }
    [XmlIgnore]
    public long PatientId { get; set; }

    // CYP101 Properties

    [XmlIgnore]
    public CYP001 CYP001 { get; set; }
    [XmlElement("CYP201")]
    public List<CYP201> CYP201 { get; set; }
}

public class CYP201
{
    [XmlIgnore]
    public int SubmissionId { get; set; }
    [XmlIgnore]
    public long ContactId { get; set; }
    [XmlIgnore]
    public long ReferralId { get; set; }

    // CYP201 Properties

    [XmlIgnore]
    public CYP101 CYP101 { get; set; }
    [XmlElement("CYP202")]
    public List<CYP202> CYP202 { get; set; }
}

public class CYP202
{
    [XmlIgnore]
    public int SubmissionId { get; set; }
    [XmlIgnore]
    public long ContactId { get; set; }
    [XmlIgnore]
    public long ContactActivityId { get; set; }

    // CYP202 Properties

    [XmlIgnore]
    public CYP201 CYP201 { get; set; }
}

DbContext

public DbSet<CYP000> CYP000 { get; set; }
public DbSet<CYP001> CYP001 { get; set; }
public DbSet<CYP002> CYP002 { get; set; }
public DbSet<CYP101> CYP101 { get; set; }
public DbSet<CYP201> CYP201 { get; set; }
public DbSet<CYP202> CYP202 { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // CYP000
    modelBuilder.Entity<CYP000>()
        .HasKey(e => e.SubmissionId);

    modelBuilder.Entity<CYP000>()
        .HasMany(e => e.CYP001)
        .WithOne(e => e.CYP000)
        .HasForeignKey(e => e.SubmissionId)
        .HasPrincipalKey(e => e.SubmissionId);

    // CYP001
    modelBuilder.Entity<CYP001>()
        .HasKey(e => new { e.SubmissionId, e.PatientId });

    modelBuilder.Entity<CYP001>()
        .HasMany(e => e.CYP101)
        .WithOne(e => e.CYP001)
        .HasForeignKey(e => new { e.SubmissionId, e.PatientId });

    modelBuilder.Entity<CYP001>()
        .HasMany(e => e.CYP002)
        .WithOne(e => e.CYP001)
        .HasForeignKey(e => new { e.SubmissionId, e.PatientId });

    // CYP002
    modelBuilder.Entity<CYP002>()
        .HasKey(e => new { e.SubmissionId, e.PatientId, e.C002020 });


    // CYP101
    modelBuilder.Entity<CYP101>()
        .HasKey(e => new { e.SubmissionId, e.ReferralId });

    modelBuilder.Entity<CYP101>()
        .HasMany(e => e.CYP201)
        .WithOne(e => e.CYP101)
        .HasForeignKey(e => new { e.SubmissionId, e.ReferralId });

    // CYP201
    modelBuilder.Entity<CYP201>()
        .HasKey(e => new { e.SubmissionId, e.ContactId });

    modelBuilder.Entity<CYP201>()
        .HasMany(e => e.CYP202)
        .WithOne(e => e.CYP201)
        .HasForeignKey(e => new { e.SubmissionId, e.ContactId });

    // CYP202
    modelBuilder.Entity<CYP202>()
        .HasKey(e => new { e.SubmissionId, e.ContactActivityId });
}
...