public void ForeignKeyCopiedFromAutoPrimaryKey_InCorrectOrder_Test()
        {
            // Arrange

            var primaryTable = new PrimaryTable();
            var primaryRecordReference = new RecordReference<PrimaryTable>(Helpers.GetTypeGeneratorMock(primaryTable).Object, this.attributeDecorator);
            primaryRecordReference.Populate();

            var foreignTable = new ForeignTable();
            var foreignRecordReference = new RecordReference<ForeignTable>(Helpers.GetTypeGeneratorMock(foreignTable).Object, this.attributeDecorator);
            foreignRecordReference.Populate();

            foreignRecordReference.AddPrimaryRecordReference(primaryRecordReference);

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

            this.writePrimitivesMock.Setup(m => m.Execute()).Returns(expected);

            // Act

            // Note the foreign key record is being passed in before the primary key record.
            // This is to test that the primary key record that wrote first gets the first return
            // data element and the foreign key record gets the subsequent one.

            this.persistence.Persist(new RecordReference[] { foreignRecordReference, primaryRecordReference });

            // Assert

            Assert.AreEqual(expected[1], primaryTable.Key);
            Assert.AreEqual(expected[5], foreignTable.Key);
        }
        private void CopyPrimaryToForeignKeys(RecordReference recordReference)
        {
            var primaryKeys = recordReference.PrimaryKeyReferences.SelectMany(
                pkRef =>
                    this.attributeDecorator.GetPropertyAttributes<PrimaryKeyAttribute>(pkRef.RecordType)
                        .Select(pkpa => new {@Object = pkRef.RecordObject, PkProperty = pkpa.PropertyInfo}));

            IEnumerable<PropertyAttribute<ForeignKeyAttribute>> foreignKeyPropertyAttributes =
                this.attributeDecorator.GetPropertyAttributes<ForeignKeyAttribute>(recordReference.RecordType);

            foreignKeyPropertyAttributes.ToList().ForEach(fkpa =>
            {
                var primaryKey =
                    primaryKeys.FirstOrDefault(
                        pk =>
                            pk.PkProperty.DeclaringType == this.attributeDecorator.GetTableType(fkpa.Attribute, recordReference.RecordType) &&
                            Helper.GetColumnName(pk.PkProperty, this.attributeDecorator) == fkpa.Attribute.PrimaryKeyName);

                if (primaryKey == null)
                {
                    return;
                }

                MemoryPersistence.Logger.Debug($"PropertyInfo to get from: {primaryKey.PkProperty}");
                object primaryKeyPropertyValue = primaryKey.PkProperty.GetValue(primaryKey.Object);
                MemoryPersistence.Logger.Debug($"primaryKeyPropertyValue: {primaryKeyPropertyValue}");

                MemoryPersistence.Logger.Debug($"PropertyInfo to set: {fkpa.PropertyInfo}");
                fkpa.PropertyInfo.SetValue(recordReference.RecordObject, primaryKeyPropertyValue);
            });
        }
        public void CopyForeignKeyColumns_Test()
        {
            // Arrange

            var target = new ManualKeyForeignTable();

            var recordReference = new RecordReference<ManualKeyForeignTable>(Helpers.GetTypeGeneratorMock(target).Object, this.attributeDecorator);
            recordReference.Populate();

            this.insertRecordService = new InsertRecordService(recordReference, this.attributeDecorator, InsertRecordServiceTest.IsKeyReferenceCheckEnforced);

            var columns = new[]
            {
                new Column { Name = "ForeignKey1", Value = "ABCD" },
                new Column { Name = "Two", Value = new Variable(null) },
                new Column { Name = "ForeignKey2", Value = 3 },
            };

            // Act

            this.insertRecordService.CopyPrimaryToForeignKeyColumns(columns);

            // Assert

            Assert.AreEqual(columns[0].Value, target.ForeignKey1);
            Assert.AreEqual(columns[2].Value, target.ForeignKey2);
        }
        public void Persists_KeyMapping_Test()
        {
            // Arrange

            var primaryTable = new ManualKeyPrimaryTable { Key1 = "ABCD", Key2 = 5 };
            var primaryReference = new RecordReference<ManualKeyPrimaryTable>(Helpers.GetTypeGeneratorMock(primaryTable).Object, this.attributeDecorator);

            var foreignTable = new ManualKeyForeignTable();
            var foreignReference =
                new RecordReference<ManualKeyForeignTable>(Helpers.GetTypeGeneratorMock(foreignTable).Object, this.attributeDecorator);

            foreignReference.AddPrimaryRecordReference(primaryReference);

            var deferredValueGeneratorMock = new Mock<IDeferredValueGenerator<LargeInteger>>();
            var persistence = new MemoryPersistence(deferredValueGeneratorMock.Object, this.attributeDecorator);

            // Act

            primaryReference.Populate();
            foreignReference.Populate();
            persistence.Persist(new RecordReference[] { primaryReference, foreignReference});

            // Assert

            Assert.AreEqual(primaryTable.Key1, foreignTable.ForeignKey1);
            Assert.AreEqual(primaryTable.Key2, foreignTable.ForeignKey2);
        }
        public InsertRecordService(RecordReference recordReference, IAttributeDecorator attributeDecorator, bool enforceKeyReferenceCheck)
        {
            InsertRecordService.Logger.Debug("Entering constructor");

            this.recordReference = recordReference;
            this.attributeDecorator = attributeDecorator;
            this.enforceKeyReferenceCheck = enforceKeyReferenceCheck;

            InsertRecordService.Logger.Debug("Exiting constructor");
        }
        public InsertRecord(InsertRecordService service, RecordReference recordReference,
            IEnumerable<AbstractRepositoryOperation> peers, IAttributeDecorator attributeDecorator)
        {
            InsertRecord.Logger.Debug("Entering constructor");

            this.Peers = peers;
            this.RecordReference = recordReference;
            this.service = service;
            this.attributeDecorator = attributeDecorator;

            InsertRecord.Logger.Debug("Exiting constructor");
        }
        public void DeferredValueGenerator_Test()
        {
            // Arrange

            var typeGeneratorMock = new Mock<ITypeGenerator>();

            typeGeneratorMock.Setup(
                m => m.GetObject<PrimaryTable>(It.IsAny<ConcurrentDictionary<PropertyInfo, Action<PrimaryTable>>>()))
                .Returns(new PrimaryTable());

            typeGeneratorMock.Setup(
                m => m.GetObject<ForeignTable>(It.IsAny<ConcurrentDictionary<PropertyInfo, Action<ForeignTable>>>()))
                .Returns(new ForeignTable());

            var recordObject1 = new RecordReference<PrimaryTable>(typeGeneratorMock.Object, this.attributeDecorator);
            var recordObject2 = new RecordReference<ForeignTable>(typeGeneratorMock.Object, this.attributeDecorator);

            var dataSource = new Mock<IPropertyDataGenerator<LargeInteger>>();
            var generator = new StandardDeferredValueGenerator<LargeInteger>(dataSource.Object);

            // Act

            recordObject1.Populate();
            recordObject2.Populate();

            generator.AddDelegate(recordObject1.RecordType.GetProperty("Text"), ul => "A");
            generator.AddDelegate(recordObject1.RecordType.GetProperty("Integer"), ul => 1);
            generator.AddDelegate(recordObject2.RecordType.GetProperty("Text"), ul => "B");
            generator.AddDelegate(recordObject2.RecordType.GetProperty("Integer"), ul => 2);

            generator.Execute(new RecordReference[] {recordObject2, recordObject1});

            // Assert

            Assert.AreEqual("A", recordObject1.RecordObject.Text);
            Assert.AreEqual(1, recordObject1.RecordObject.Integer);
            Assert.AreEqual("B", recordObject2.RecordObject.Text);
            Assert.AreEqual(2, recordObject2.RecordObject.Integer);
        }
        public void Initialize()
        {
            XmlConfigurator.Configure();

            this.foreignKeyTable = new ForeignTable();

            this.attributeDecorator = new StandardAttributeDecorator(attributeDecorator => null, null);
            this.typeGeneratorMock = Helpers.GetTypeGeneratorMock(this.foreignKeyTable);
            this.recordReference = new RecordReference<ForeignTable>(this.typeGeneratorMock.Object, this.attributeDecorator);
            this.recordReference.Populate();
            this.insertRecordService = new InsertRecordService(this.recordReference, this.attributeDecorator, InsertRecordServiceTest.IsKeyReferenceCheckEnforced);
            this.writerMock = new Mock<IWritePrimitives>();
            this.peers = Enumerable.Empty<AbstractRepositoryOperation>();

            this.mainTableColumns = Helpers.GetColumns(this.foreignKeyTable, this.attributeDecorator);
        }
        public void GetRegularColumns_WriteGuid_Test()
        {
            // Arrange

            var table = new ClassWithGuidKeys();

            Mock<ITypeGenerator> typeGeneratorMock = Helpers.GetTypeGeneratorMock(table);

            var recordReference = new RecordReference<ClassWithGuidKeys>(typeGeneratorMock.Object, this.attributeDecorator);
            recordReference.Populate();

            var insertRecordService = new InsertRecordService(recordReference, this.attributeDecorator, InsertRecordServiceTest.IsKeyReferenceCheckEnforced);

            Variable v1, v2, v3;
            this.writerMock.Setup(m => m.WriteGuid("Key1")).Returns(v1 = new Variable("x"));
            this.writerMock.Setup(m => m.WriteGuid("Key3")).Returns(v2 = new Variable("y"));
            this.writerMock.Setup(m => m.WriteGuid("Key4")).Returns(v3 = new Variable("z"));

            // Act

            List<Column> regularColumns = insertRecordService.GetRegularColumns(this.writerMock.Object).ToList();

            // Assert

            this.writerMock.Verify(m => m.WriteGuid(It.IsAny<string>()), Times.Exactly(3));

            Column key1 = regularColumns.First(c => c.Name == "Key1");
            Column key3 = regularColumns.First(c => c.Name == "Key3");
            Column key4 = regularColumns.First(c => c.Name == "Key4");

            Assert.AreEqual(v1, key1.Value);
            Assert.AreEqual(v2, key3.Value);
            Assert.AreEqual(v3, key4.Value);
        }
        public void GetRegularColumns_NonAutoPrimaryKey_Test()
        {
            // Arrange

            var table = new ManualKeyPrimaryTable {Key1 = "ABCD", Key2 = 7};

            var typeGeneratorMock = Helpers.GetTypeGeneratorMock(table);
            var recordReference = new RecordReference<ManualKeyPrimaryTable>(typeGeneratorMock.Object, this.attributeDecorator);
            recordReference.Populate();
            var insertRecordService = new InsertRecordService(recordReference, this.attributeDecorator, InsertRecordServiceTest.IsKeyReferenceCheckEnforced);

            // Act

            List<Column> regularColumns = insertRecordService.GetRegularColumns(null).ToList();

            // Assert

            Assert.AreEqual(2, regularColumns.Count);

            Column stringKey = regularColumns.First(c => c.Name == "Key1");
            Column intKey = regularColumns.First(c => c.Name == "Key2");

            Assert.AreEqual(table.Key1, stringKey.Value);
            Assert.AreEqual(table.Key2, intKey.Value);
        }
        public void GetRegularColumns_ExplicitlySetGuid_Test()
        {
            // Arrange

            var table = new ClassWithGuidKeys {Key1 = Guid.NewGuid(), Key3 = Guid.NewGuid(), Key4 = null};

            Mock<ITypeGenerator> typeGeneratorMock = Helpers.GetTypeGeneratorMock(table);
            var recordReference = new RecordReference<ClassWithGuidKeys>(typeGeneratorMock.Object, this.attributeDecorator);

            recordReference.Set(r => r.Key1, Guid.Empty).Set(r => r.Key3, Guid.Empty).Set(r => r.Key4, Guid.Empty);
            recordReference.Populate();

            var insertRecordService = new InsertRecordService(recordReference, this.attributeDecorator, InsertRecordServiceTest.IsKeyReferenceCheckEnforced);

            // Act

            List<Column> regularColumns = insertRecordService.GetRegularColumns(null).ToList();

            // Assert

            Column key1 = regularColumns.First(c => c.Name == "Key1");
            Column key3 = regularColumns.First(c => c.Name == "Key3");
            Column key4 = regularColumns.First(c => c.Name == "Key4");

            Assert.AreEqual(table.Key1, key1.Value);
            Assert.AreEqual(table.Key3, key3.Value);
            Assert.AreEqual(null, key4.Value);
        }
        public void GetPrimaryKeyOperations_Test()
        {
            // Arrange

            Mock<ITypeGenerator> subjectTypeGeneratorMock = Helpers.GetTypeGeneratorMock(new SubjectClass());
            Mock<ITypeGenerator> primaryTableTypeGeneratorMock = Helpers.GetTypeGeneratorMock(new PrimaryTable());

            var peerRecordreferences = new RecordReference[]
            {
                new RecordReference<SubjectClass>(subjectTypeGeneratorMock.Object, this.attributeDecorator),
                new RecordReference<PrimaryTable>(primaryTableTypeGeneratorMock.Object, this.attributeDecorator),
                new RecordReference<SubjectClass>(subjectTypeGeneratorMock.Object, this.attributeDecorator),
                new RecordReference<PrimaryTable>(primaryTableTypeGeneratorMock.Object, this.attributeDecorator),
            };

            InsertRecord[] peerOperations = peerRecordreferences.Select(r => new InsertRecord(this.insertRecordService, r, this.peers, this.attributeDecorator)).ToArray();

            // Act

            this.recordReference.AddPrimaryRecordReference(peerRecordreferences[1], peerRecordreferences[3]);

            InsertRecord[] primaryKeyOperations =
                this.insertRecordService.GetPrimaryKeyOperations(peerOperations).ToArray();

            // Assert

            Assert.AreEqual(2, primaryKeyOperations.Length);
            Assert.AreEqual(peerOperations[1], primaryKeyOperations[0]);
            Assert.AreEqual(peerOperations[3], primaryKeyOperations[1]);
        }
        public void GetForeignKeyColumns_PropertyIsExplicitlySet_Test()
        {
            // Arrange

            const int explicitValue = 7;

            this.foreignKeyTable.ForeignKey = explicitValue;  // Simulate getting expicitly set value from type generator

            var primaryKeySymbols = new List<ColumnSymbol>
            {
                new ColumnSymbol {ColumnName = "Key", TableType = typeof (PrimaryTable), Value = 5}
            };

            var recordReference =
                new RecordReference<PrimaryTable>(Helpers.GetTypeGeneratorMock(new PrimaryTable()).Object, this.attributeDecorator);

            var primaryKeyInsertRecordMock = new Mock<InsertRecord>(this.insertRecordService, recordReference, this.peers, this.attributeDecorator);

            primaryKeyInsertRecordMock.Setup(m => m.GetPrimaryKeySymbols()).Returns(primaryKeySymbols);

            // Just record the fact that "ForeignKey" is explicitly set. Actual value comes from explicit value above.
            this.recordReference.Set(r => r.ForeignKey, default(int));

            // Act

            List<ExtendedColumnSymbol> fkColumns =
                this.insertRecordService.GetForeignKeyColumns(new[] { primaryKeyInsertRecordMock.Object }).ToList();

            // Assert

            Assert.AreEqual(1, fkColumns.Count);
            Assert.AreEqual("ForeignKey", fkColumns[0].ColumnName);
            Assert.AreEqual(explicitValue, fkColumns[0].Value);
        }
        public void Insert_Test()
        {
            // Arrange

            var primaryTable = new PrimaryTable { Integer = 5, Text = "Text"};

            var primaryRecordReference = new RecordReference<PrimaryTable>(Helpers.GetTypeGeneratorMock(primaryTable).Object, this.attributeDecorator);
            primaryRecordReference.Populate();

            string tableName = typeof(PrimaryTable).Name;

            List<Column> primaryTableColumns = null;

            this.writePrimitivesMock.Setup(m => m.Insert(null, It.IsAny<string>(), tableName, It.IsAny<IEnumerable<Column>>()))
                .Callback<string, string, string, IEnumerable<Column>>((cat, s, t, col) => primaryTableColumns = col.ToList());

            this.writePrimitivesMock.Setup(m => m.Execute()).Returns(new object[] {"Key", 0, "Guid", Guid.NewGuid()});

            // Act

            var recordReferenceArray = new RecordReference[] {primaryRecordReference};

            this.persistence.Persist(recordReferenceArray);

            // Assert

            this.writePrimitivesMock.Verify(m => m.Insert(null, It.IsAny<string>(), tableName, It.IsAny<IEnumerable<Column>>()), Times.Once());

            this.deferredValueGeneratorMock.Verify(
                m => m.Execute(It.Is<IEnumerable<RecordReference>>(e => e.First() == recordReferenceArray[0])),
                Times.Once);

            Assert.IsNotNull(primaryTableColumns);
            Assert.AreEqual(4, primaryTableColumns.Count);

            Assert.AreEqual("Text", primaryTableColumns[0].Name);
            Assert.AreEqual(primaryTable.Text, primaryTableColumns[0].Value);

            Assert.AreEqual("Integer", primaryTableColumns[1].Name);
            Assert.AreEqual(primaryTable.Integer, primaryTableColumns[1].Value);
        }
        public void InsertsInProperOrder_Test()
        {
            // Arrange

            var primaryTable = new PrimaryTable { Integer = 1};
            var primaryRecordReference = new RecordReference<PrimaryTable>(Helpers.GetTypeGeneratorMock(primaryTable).Object, this.attributeDecorator);
            primaryRecordReference.Populate();

            var foreignTable = new ForeignTable {Integer = 1};
            var foreignRecordReference = new RecordReference<ForeignTable>(Helpers.GetTypeGeneratorMock(foreignTable).Object, this.attributeDecorator);
            foreignRecordReference.Populate();

            foreignRecordReference.AddPrimaryRecordReference(primaryRecordReference);

            var columns = new List<List<Column>>();

            this.writePrimitivesMock.Setup(m => m.Insert(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IEnumerable<Column>>()))
                .Callback<string, string, string, IEnumerable<Column>>((cat, s, t, col) => columns.Add(col.ToList()));

            this.writePrimitivesMock.Setup(m => m.SelectIdentity(It.IsAny<string>())).Returns(new Variable(null));

            this.writePrimitivesMock.Setup(m => m.Execute()).Returns(new object[] {"Key", 0, "Guid", Guid.NewGuid(), "Key", 0});

            // Act

            // Note the foreign key record is being passed in before the primary key record
            // to test that the primary key record writes first regardless which insert operation's
            // Write method is called.

            this.persistence.Persist(new RecordReference[] { foreignRecordReference, primaryRecordReference});

            // Assert

            Assert.AreEqual(primaryTable.Integer, columns[0].First(c => c.Name == "Integer").Value);
            Assert.AreEqual(foreignTable.Integer, columns[1].First(c => c.Name == "Integer").Value);
        }
        public virtual void AddPrimaryRecordReference(RecordReference primaryRecordReference)
        {
            RecordReference.Logger.Debug(
                $"Entering AddPrimaryRecordReference(RecordReference). record object: {primaryRecordReference.RecordObject}");

            if (!this.ValidateRelationship(primaryRecordReference))
            {
                throw new NoReferentialIntegrityException(primaryRecordReference.RecordType, this.RecordType);
            }

            ((List<RecordReference>)this.PrimaryKeyReferences).Add(primaryRecordReference);

            RecordReference.Logger.Debug("Exiting AddPrimaryRecordReference(RecordReference)");
        }
        protected virtual bool ValidateRelationship(RecordReference primaryRecordReference)
        {
            RecordReference.Logger.Debug("Entering ValidateRelationship");

            IEnumerable<PropertyAttribute<ForeignKeyAttribute>> foreignKeyPropertyAttributes =
                this.AttributeDecorator.GetPropertyAttributes<ForeignKeyAttribute>(this.RecordType).ToList();

            bool result =
                    this.AttributeDecorator.GetPropertyAttributes<PrimaryKeyAttribute>(primaryRecordReference.RecordType)
                    .All(
                        pkPa =>
                            foreignKeyPropertyAttributes.Any(
                                fkPa =>
                                    pkPa.PropertyInfo.DeclaringType == this.AttributeDecorator.GetTableType(fkPa.Attribute, this.RecordType)
                                    &&
                                    Helper.GetColumnName(pkPa.PropertyInfo, this.AttributeDecorator)
                                        .Equals(fkPa.Attribute.PrimaryKeyName, StringComparison.Ordinal)
                                    &&
                                    pkPa.PropertyInfo.PropertyType == fkPa.PropertyInfo.PropertyType
                                )
                    );

            RecordReference.Logger.Debug("Exiting ValidateRelationship");

            return result;
        }
        public void ForeignKeysCopiedFromManualPrimaryKeys_Test()
        {
            // Arrange

            var primaryTable = new ManualKeyPrimaryTable {Key1 = "A", Key2 = 7};
            var foreignTable = new ManualKeyForeignTable();

            var primaryRecordReference = new RecordReference<ManualKeyPrimaryTable>(Helpers.GetTypeGeneratorMock(primaryTable).Object, this.attributeDecorator);
            primaryRecordReference.Populate();

            var foreignRecordReference = new RecordReference<ManualKeyForeignTable>(Helpers.GetTypeGeneratorMock(foreignTable).Object, this.attributeDecorator);
            foreignRecordReference.Populate();

            foreignRecordReference.AddPrimaryRecordReference(primaryRecordReference);
            const string catalogueName = "catABC";
            const string schema = "schemaABC";
            const string tableName = "ABCD";

            var columns = new List<List<Column>>();

            this.writePrimitivesMock.Setup(m => m.Insert(catalogueName, schema, tableName, It.IsAny<IEnumerable<Column>>()))
                .Callback<string, string, string, IEnumerable<Column>>((cat, s, t, col) => columns.Add(col.ToList()));

            // Act

            this.persistence.Persist(new RecordReference[] { foreignRecordReference, primaryRecordReference });

            // Assert

            Assert.AreEqual(primaryTable.Key1, foreignTable.ForeignKey1);
            Assert.AreEqual(primaryTable.Key2, foreignTable.ForeignKey2);
        }
        public void CopyForeignKeyColumns_UnknownColumnThrows_Test()
        {
            // Arrange

            var target = new ManualKeyForeignTable();

            var recordReference = new RecordReference<ManualKeyForeignTable>(Helpers.GetTypeGeneratorMock(target).Object, this.attributeDecorator);
            recordReference.Populate();

            this.insertRecordService = new InsertRecordService(recordReference, this.attributeDecorator, InsertRecordServiceTest.IsKeyReferenceCheckEnforced);

            var columns = new[]
            {
                new Column { Name = "ForeignKey1", Value = "ABCD" },
                new Column { Name = "Two", Value = new object() },
            };

            // Act
            // Assert

            Helpers.ExceptionTest(
                () => this.insertRecordService.CopyPrimaryToForeignKeyColumns(columns),
                typeof(InvalidOperationException),
                "Sequence contains no matching element");
        }
        public void Persist_Test()
        {
            // Arrange

            var deferredValueGeneratorMock = new Mock<IDeferredValueGenerator<LargeInteger>>();

            var persistence = new MemoryPersistence(deferredValueGeneratorMock.Object, this.attributeDecorator);

            var primaryTable = new PrimaryTable { Integer = 5, Text = "Text" };

            var primaryRecordReference = new RecordReference<PrimaryTable>(
                Helpers.GetTypeGeneratorMock(primaryTable).Object,
                this.attributeDecorator);

            var recordReferenceArray = new RecordReference[] { primaryRecordReference };

            // Act

            persistence.Persist(recordReferenceArray);

            // Assert

            deferredValueGeneratorMock.Verify(
                m => m.Execute(It.Is<IEnumerable<RecordReference>>(e => e.First() == recordReferenceArray[0])),
                Times.Once);
        }