Example #1
0
        /// <summary>
        /// Merges the specified <paramref name="submission"/> into the repository backed by the <paramref name="provider"/>.
        /// </summary>
        /// <param name="submission">
        /// The submission.
        /// </param>
        /// <param name="provider">
        /// The provider.
        /// </param>
        private void MergeSubmission(GenericSubmission submission, IRepositoryProvider provider)
        {
            // Merge our existing fields
            var fields     = submission.SubmissionValues.Select(value => value.Field).Distinct().ToList();
            var fieldItems = from f in fields
                             select new FieldRow
            {
                Name        = f.Name,
                Description = f.Description
            };

            // Merge in the field values.
            var commandProvider = new JsonCommandFactory();
            var transaction     = provider.BeginTransaction();

            var fieldsCommand = new JsonInsert <FieldRow>(provider.DatabaseContext).OnConflict(row => row.Name)
                                .Upsert(row => row.Description)
                                .Returning(row => row.FieldId, row => row.Name, row => row.Description);

            var mergedFields = fieldsCommand.ExecuteForResults(fieldItems).ToList();

            foreach (var field in fields)
            {
                var input = mergedFields.FirstOrDefault(f => string.Equals(f.Name, field.Name, StringComparison.Ordinal));

                // Because we are doing a subset, and we know we will get back baseline fields. If MERGE is messed up this will error later when there
                // aren't IDs for baseline fields.
                if (input == null)
                {
                    continue;
                }

                this.mapper.MapTo(input, field);
            }

            var submissionRepository = new EntityRepository <GenericSubmission, GenericSubmissionRow>(provider, this.mapper);

            submissionRepository.Save(submission);

            // Could be mapped as well.
            var fieldValues = from v in submission.SubmissionValues
                              select new FieldValueTableTypeRow
            {
                FieldId = v.Field.FieldId.GetValueOrDefault(),
                LastModifiedByDomainIdentifierId = v.LastModifiedBy.DomainIdentityId.GetValueOrDefault(),
                LastModifiedTime = v.LastModifiedTime
            };

            // We use FieldValueId to essentially ensure we're only affecting the scope of this submission. FieldId on the select brings back
            // only inserted rows matched back to their original fields.
            var fieldValueCommand = new JsonInsert <FieldValueRow>(provider.DatabaseContext);
            var mergedFieldValues = fieldValueCommand.OnConflict(row => row.FieldValueId)
                                    .Upsert(row => row.LastModifiedByDomainIdentifierId, row => row.LastModifiedTime)
                                    .Returning(row => row.FieldValueId, row => row.FieldId, row => row.LastModifiedByDomainIdentifierId, row => row.LastModifiedTime)
                                    .ExecuteForResults(fieldValues)
                                    .ToList();

            Assert.IsTrue(mergedFieldValues.All(row => row.FieldValueId > 0));

            // Map back to the domain object.
            foreach (var value in submission.SubmissionValues)
            {
                var input = mergedFieldValues.First(row => row.FieldId == value.Field.FieldId);
                this.mapper.MapTo(input, value);
                Assert.IsTrue(value.FieldValueId.HasValue);
            }

            // Now merge in the field value elements.
            // Do the field value elements
            var valueElements = (from e in submission.SubmissionValues.SelectMany(value => value.Elements)
                                 select new FieldValueElementPgFlatRow
            {
                FieldValueElementId = e.FieldValueElementId,
                FieldValueId = e.FieldValue.FieldValueId.GetValueOrDefault(),
                Order = e.Order,
                DateElement = e.Element as DateTimeOffset? ?? e.Element as DateTime?,
                FloatElement = e.Element as double? ?? e.Element as float?,
                IntegerElement = e.Element as long? ?? e.Element as int? ?? e.Element as short? ?? e.Element as byte?,
                MoneyElement = e.Element as decimal?,
                TextElement = e.Element as string                      // here we actually want it to be null if it is not a string
            }).ToList();

            var elementMergeCommand = new JsonInsert <FieldValueElementRow>(provider.DatabaseContext);
            var mergedValueElements = elementMergeCommand.OnConflict(row => row.FieldValueElementId)
                                      .Upsert(row => row.Order)
                                      .Returning(row => row.FieldValueElementId, row => row.FieldValueId, row => row.Order)
                                      .ExecuteForResults(valueElements)
                                      .ToList();

            foreach (var element in valueElements)
            {
                var input = mergedValueElements.First(row => row.FieldValueId == element.FieldValueId && row.Order == element.Order);
                this.mapper.MapTo(input, element);
                Assert.IsTrue(element.FieldValueElementId.HasValue);
            }

            var dateElementsCommand = new JsonInsert <DateElementRow>(provider.DatabaseContext)
                                      .From <FieldValueElementPgFlatRow>(row => row.FieldValueElementId, row => row.DateElement)
                                      .OnConflict(row => row.DateElementId)
                                      .Upsert(row => row.Value);

            dateElementsCommand.Execute(valueElements.Where(row => row.DateElement.HasValue));

            var floatElementsCommand = new JsonInsert <FloatElementRow>(provider.DatabaseContext)
                                       .From <FieldValueElementPgFlatRow>(row => row.FieldValueElementId, row => row.FloatElement)
                                       .OnConflict(row => row.FloatElementId)
                                       .Upsert(row => row.Value);

            floatElementsCommand.Execute(valueElements.Where(row => row.FloatElement.HasValue));

            var integerElementsCommand = new JsonInsert <IntegerElementRow>(provider.DatabaseContext)
                                         .From <FieldValueElementPgFlatRow>(row => row.FieldValueElementId, row => row.IntegerElement)
                                         .OnConflict(row => row.IntegerElementId)
                                         .Upsert(row => row.Value);

            integerElementsCommand.Execute(valueElements.Where(row => row.IntegerElement.HasValue));

            var moneyElementsCommand = new JsonInsert <MoneyElementRow>(provider.DatabaseContext)
                                       .From <FieldValueElementPgFlatRow>(row => row.FieldValueElementId, row => row.MoneyElement)
                                       .OnConflict(row => row.MoneyElementId)
                                       .Upsert(row => row.Value);

            moneyElementsCommand.Execute(valueElements.Where(row => row.MoneyElement.HasValue));

            var textElementsCommand = new JsonInsert <TextElementRow>(provider.DatabaseContext)
                                      .From <FieldValueElementPgFlatRow>(row => row.FieldValueElementId, row => row.TextElement)
                                      .OnConflict(row => row.TextElementId)
                                      .Upsert(row => row.Value);

            textElementsCommand.Execute(valueElements.Where(row => row.TextElement != null));

            // Attach the values to the submission
            var genericValueSubmissions = from v in mergedFieldValues
                                          select new GenericSubmissionValueTableTypeRow
            {
                GenericSubmissionId      = submission.GenericSubmissionId.GetValueOrDefault(),
                GenericSubmissionValueId = v.FieldValueId
            };

            var submissionCommand = new JsonInsert <GenericSubmissionValueRow>(provider.DatabaseContext).Upsert(
                row => row.GenericSubmissionValueId,
                row => row.GenericSubmissionId);

            ////.DeleteUnmatchedInSource(row => row.GenericSubmissionId); Can't with PostgreSQL

            submissionCommand.Execute(genericValueSubmissions);
            transaction.Commit();
        }