public void WritePrimaryKeyOperations_Test()
        {
            // Arrange

            var primaryKeyOperations = new[]
            {
                new Mock<InsertRecord>(this.insertRecordService, null, this.peers, null),
                new Mock<InsertRecord>(this.insertRecordService, null, this.peers, null),
            };

            // Act

            var breaker = new CircularReferenceBreaker();
            var currentOrder = new Counter();
            var orderedOperations = new AbstractRepositoryOperation[0];

            this.insertRecordService.WritePrimaryKeyOperations(this.writerMock.Object,
                primaryKeyOperations.Select(m => m.Object), breaker, currentOrder, orderedOperations);

            // Assert

            primaryKeyOperations.ToList()
                .ForEach(
                    o =>
                        o.Verify(m => m.Write(breaker, this.writerMock.Object, currentOrder, orderedOperations),
                            Times.Once));
        }
        public void Write_Test()
        {
            // Arrange

            var orderedOperations = new AbstractRepositoryOperation[1];
            var primaryKeyOperations = new List<InsertRecord>();
            var currentOrder = new Counter();
            var regularColumns = new List<Column>();
            var foreignKeyColumns = new List<ExtendedColumnSymbol>();
            var columnList = regularColumns.Concat(Helpers.ColumnSymbolToColumn(foreignKeyColumns));
            string tableName = typeof (SubjectClass).Name;

            this.serviceMock.Setup(m => m.GetPrimaryKeyOperations(this.peers)).Returns(primaryKeyOperations);
            this.serviceMock.Setup(m => m.GetRegularColumns(this.writePrimitivesMock.Object)).Returns(regularColumns);
            this.serviceMock.Setup(m => m.GetForeignKeyColumns(primaryKeyOperations)).Returns(foreignKeyColumns);

            // Act

            this.insertRecord.Write(this.breakerMock.Object, this.writePrimitivesMock.Object, currentOrder, orderedOperations);

            // Assert

            this.breakerMock.Verify(m => m.Push<IWritePrimitives, Counter, AbstractRepositoryOperation[]>(this.insertRecord.Write), Times.Once);
            this.serviceMock.Verify(m => m.GetPrimaryKeyOperations(this.peers), Times.Once);
            this.serviceMock.Verify(
                m =>
                    m.WritePrimaryKeyOperations(this.writePrimitivesMock.Object, primaryKeyOperations,
                        this.breakerMock.Object, currentOrder, orderedOperations), Times.Once);

            this.serviceMock.Verify(m => m.GetRegularColumns(this.writePrimitivesMock.Object), Times.Once);
            this.serviceMock.Verify(m => m.GetForeignKeyColumns(primaryKeyOperations), Times.Once);

            Assert.AreEqual(this.insertRecord, orderedOperations[0]);

            this.serviceMock.Verify(
                m =>
                    m.WritePrimitives(this.writePrimitivesMock.Object, null, It.IsAny<string>(), tableName, columnList,
                        It.Is<List<ColumnSymbol>>(l => l.Count == 0)), Times.Once);

            this.serviceMock.Verify(m => m.CopyPrimaryToForeignKeyColumns(It.Is<IEnumerable<Column>>(c => !c.Any())), Times.Once());
        }
        public void Read_AutoKey_Test()
        {
            // Arrange

            var record = new PrimaryTable();

            this.recordReferenceMock.Setup(m => m.RecordObject).Returns(record);
            this.recordReferenceMock.Setup(m => m.RecordType).Returns(record.GetType());

            var streamReadPointer = new Counter();

            const int expected = 8;

            var returnValue = new object[] { "Key", expected, "Guid", Guid.NewGuid() };

            // Act

            this.insertRecord.Write(this.breakerMock.Object, this.writePrimitivesMock.Object, new Counter(), new AbstractRepositoryOperation[1]);
            this.insertRecord.Read(streamReadPointer, returnValue);

            // Assert

            Assert.AreEqual(expected, record.Key);
            Assert.AreEqual(4, streamReadPointer.Value);
        }
        public override void Read(Counter readStreamPointer, object[] data)
        {
            InsertRecord.Logger.Debug($"Entering Read. readStreamPointer.Value: {readStreamPointer.Value}, data: {string.Join(",", data)}");

            IEnumerable<PropertyAttributes> propertyAttributes =
                this.attributeDecorator.GetPropertyAttributes(this.RecordReference.RecordType).ToList();

            List<PropertyInfo> propertiesForRead = this.GetPropertiesForRead(propertyAttributes).ToList();

            InsertRecord.Logger.Debug(
                $"propertiesForRead: {string.Join(",", propertiesForRead.Select(p => p.GetExtendedMemberInfoString()))}");

            while (propertiesForRead.Any())
            {
                var columnName = (string) data[readStreamPointer.Value++];

                PropertyInfo property = propertiesForRead.First(
                    p => Helper.GetColumnName(p, this.attributeDecorator).Equals(columnName, StringComparison.Ordinal)
                    );

                try
                {
                    property.SetValue(this.RecordReference.RecordObject,
                        data[readStreamPointer.Value] is IConvertible
                            ? Convert.ChangeType(data[readStreamPointer.Value++], property.PropertyType)
                            : data[readStreamPointer.Value++]);
                }
                catch (OverflowException overflowException)
                {
                    throw new OverflowException(
                        string.Format(Messages.TypeTooNarrow, property.GetExtendedMemberInfoString(),
                            data[readStreamPointer.Value - 1]), overflowException);
                }

                propertiesForRead.Remove(property);
            }

            IEnumerable<ExtendedColumnSymbol> specialForeignKeyColumns =
                this.foreignKeyColumns.Where(c => c.Value.IsSpecialType());

            InsertRecord.Logger.Debug("Iterating specialForeignKeyColumns");

            specialForeignKeyColumns.ToList().ForEach(fkColumn =>
            {
                InsertRecord.Logger.Debug($"fkColumn: {fkColumn}");

                InsertRecord primaryKeyOperation = this.primaryKeyOperations.First(selectedPrimaryKeyOperation =>
                    selectedPrimaryKeyOperation.RecordReference.RecordType ==
                    this.attributeDecorator.GetTableType(fkColumn.PropertyAttribute.Attribute, fkColumn.TableType));

                InsertRecord.Logger.Debug($"primaryKeyOperation: {primaryKeyOperation}");

                PropertyInfo primaryKeyProperty =
                    this.GetPrimaryKeyProperty(primaryKeyOperation.RecordReference.RecordType,
                        fkColumn.PropertyAttribute.Attribute);

                InsertRecord.Logger.Debug($"primaryKeyProperty : {primaryKeyProperty.GetExtendedMemberInfoString()}");

                fkColumn.PropertyAttribute.PropertyInfo.SetValue(this.RecordReference.RecordObject,
                    primaryKeyProperty.GetValue(primaryKeyOperation.RecordReference.RecordObject));
            });

            InsertRecord.Logger.Debug("Exiting Read");
        }
        public void Read_ManualKey_Test()
        {
            // Arrange

            var record = new ClassWithGuidKeys();

            this.recordReferenceMock.Setup(m => m.RecordObject).Returns(record);
            this.recordReferenceMock.Setup(m => m.RecordType).Returns(record.GetType());

            var streamReadPointer = new Counter();

            var returnValue = new object[] { "Key1", Guid.NewGuid(), "Key3", Guid.NewGuid(), "Key4", Guid.NewGuid() };

            // Act

            this.insertRecord.Write(this.breakerMock.Object, this.writePrimitivesMock.Object, new Counter(), new AbstractRepositoryOperation[1]);
            this.insertRecord.Read(streamReadPointer, returnValue);

            // Assert

            Assert.AreEqual(returnValue[1], record.Key1);
            Assert.AreEqual(returnValue[3], record.Key3);
            Assert.AreEqual(6, streamReadPointer.Value);
        }
        public override void Write(CircularReferenceBreaker breaker, IWritePrimitives writer, Counter order, AbstractRepositoryOperation[] orderedOperations)
        {
            InsertRecord.Logger.Debug("Entering Write:" + this);
            InsertRecord.Logger.Debug($"breaker: {breaker}");

            if (breaker.IsVisited<IWritePrimitives, Counter, AbstractRepositoryOperation[]>(this.Write))
            {
                InsertRecord.Logger.Debug("Write already visited. Exiting");
                return;
            }

            if (this.IsWriteDone)
            {
                InsertRecord.Logger.Debug("Write already done. Exiting");
                return;
            }

            breaker.Push<IWritePrimitives, Counter, AbstractRepositoryOperation[]>(this.Write);

            this.primaryKeyOperations = this.service.GetPrimaryKeyOperations(this.Peers).ToList();

            this.service.WritePrimaryKeyOperations(writer, this.primaryKeyOperations, breaker, order, orderedOperations);

            Columns columnData = this.GetColumnData(writer);

            this.Order = order.Value++;
            InsertRecord.Logger.Debug($"this.Order: {this.Order}");
            orderedOperations[this.Order] = this;

            TableName tableName = Helper.GetTableName(this.RecordReference.RecordType, this.attributeDecorator);

            this.service.WritePrimitives(writer, tableName.CatalogueName, tableName.Schema, tableName.Name, columnData.AllColumns, this.primaryKeyValues);

            this.service.CopyPrimaryToForeignKeyColumns(columnData.ForeignKeyColumns);

            this.IsWriteDone = true;

            breaker.Pop();

            InsertRecord.Logger.Debug("Exiting Write");
        }
        public virtual void WritePrimaryKeyOperations(IWritePrimitives writer, IEnumerable<AbstractRepositoryOperation> primaryKeyOperations,
            CircularReferenceBreaker breaker, Counter order, AbstractRepositoryOperation[] orderedOperations)
        {
            InsertRecordService.Logger.Debug("Entering WritePrimaryKeyOperations");

            primaryKeyOperations = primaryKeyOperations.ToList();

            InsertRecordService.Logger.Debug($"primaryKeyOperations: {primaryKeyOperations.GetRecordTypesString()}");
            InsertRecordService.Logger.Debug($"order: {order.Value}");

            InsertRecordService.Logger.Debug($"orderedOperations: {orderedOperations.GetRecordTypesString()}");

            primaryKeyOperations.ToList().ForEach(o => o.Write(breaker, writer, order, orderedOperations));

            InsertRecordService.Logger.Debug("Exiting WritePrimaryKeyOperations");
        }
        public virtual void Persist(IEnumerable<RecordReference> recordReferences)
        {
            SqlClientPersistence.Logger.Debug("Entering Persist");

            recordReferences = recordReferences.ToList();

            if (!recordReferences.Any())
            {
                SqlClientPersistence.Logger.Debug("Empty recordReference collection. Exiting.");
                return;
            }

            SqlClientPersistence.Logger.Debug(
                $"Records: {string.Join(", ", recordReferences.Select(r => r?.RecordObject))}");

            this.deferredValueGenerator.Execute(recordReferences);

            var operations = new List<AbstractRepositoryOperation>();

            foreach (RecordReference recordReference in recordReferences)
            {
                operations.Add(
                    new InsertRecord(
                        new InsertRecordService(recordReference, this.attributeDecorator, this.enforceKeyReferenceCheck),
                        recordReference, operations, this.attributeDecorator));
            }

            var orderedOperations = new AbstractRepositoryOperation[operations.Count];

            var currentOrder = new Counter();

            foreach (AbstractRepositoryOperation operation in operations)
            {
                operation.Write(new CircularReferenceBreaker(), this.writePrimitives, currentOrder,
                    orderedOperations);
            }

            var readStreamPointer = new Counter();

            object[] returnValues = this.writePrimitives.Execute();

            foreach (AbstractRepositoryOperation orderedOperation in orderedOperations)
            {
                orderedOperation.Read(readStreamPointer, returnValues);
            }

            SqlClientPersistence.Logger.Debug("Exiting Persist");
        }
 public abstract void Write(CircularReferenceBreaker breaker, IWritePrimitives writer, Counter order, AbstractRepositoryOperation[] orderedOperations);
 public abstract void Read(Counter readStreamPointer, object[] data);