Index: Core/Common/src/Core.Common.IO/Core.Common.IO.csproj =================================================================== diff -u -r1795be9025cb0e054dca86a5275203966c0a9b2a -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Core/Common/src/Core.Common.IO/Core.Common.IO.csproj (.../Core.Common.IO.csproj) (revision 1795be9025cb0e054dca86a5275203966c0a9b2a) +++ Core/Common/src/Core.Common.IO/Core.Common.IO.csproj (.../Core.Common.IO.csproj) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -48,6 +48,8 @@ + + Index: Core/Common/src/Core.Common.IO/Exceptions/ConversionException.cs =================================================================== diff -u --- Core/Common/src/Core.Common.IO/Exceptions/ConversionException.cs (revision 0) +++ Core/Common/src/Core.Common.IO/Exceptions/ConversionException.cs (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -0,0 +1,58 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.Runtime.Serialization; + +namespace Core.Common.IO.Exceptions +{ + /// + /// The exception that is thrown when an error occured while converting a value from + /// the database. + /// + [Serializable] + public class ConversionException : Exception + { + /// + /// Initializes a new instance of the class. + /// + public ConversionException() {} + + /// + /// Initializes a new instance of the class + /// with a specified error message. + /// + /// The error message that explains the reason for the exception. + public ConversionException(string message) : base(message) {} + + /// + /// Initializes a new instance of the class + /// with a specified error message and a reference to the inner exception that is + /// the cause of this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, + /// or a null reference if no inner exception is specified. + public ConversionException(string message, Exception inner) : base(message, inner) {} + + protected ConversionException(SerializationInfo info, StreamingContext context) : base(info, context) {} + } +} \ No newline at end of file Index: Core/Common/src/Core.Common.IO/Readers/IDataReaderExtensions.cs =================================================================== diff -u --- Core/Common/src/Core.Common.IO/Readers/IDataReaderExtensions.cs (revision 0) +++ Core/Common/src/Core.Common.IO/Readers/IDataReaderExtensions.cs (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -0,0 +1,82 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.Data; +using System.Globalization; +using Core.Common.IO.Exceptions; + +namespace Core.Common.IO.Readers +{ + public static class IDataReaderExtensions + { + /// + /// Reads a value at column from the database. + /// + /// The expected type of value in the column with name . + /// The data reader to read a column of a certain type from. + /// The name of the column to read from. + /// The read value from the column with name . + /// Thrown when or + /// is null. + /// Thrown when the value in the column was not of type . + public static T Read(this IDataReader dataReader, string columnName) + { + if (dataReader == null) + { + throw new ArgumentNullException("dataReader"); + } + if (columnName == null) + { + throw new ArgumentNullException("columnName"); + } + + var value = dataReader[columnName]; + var conversionType = typeof(T); + + try + { + return (T) Convert.ChangeType(value, conversionType); + } + catch (InvalidCastException) + { + throw new ConversionException( + string.Format(CultureInfo.CurrentCulture, "Value read from data reader ('{0}') could not be cast to desired type {1}.", + value, + conversionType)); + } + catch (FormatException) + { + throw new ConversionException( + string.Format(CultureInfo.CurrentCulture, "Value read from data reader ('{0}') is an incorrect format to transform to type {1}.", + value, + conversionType)); + } + catch (OverflowException) + { + throw new ConversionException( + string.Format(CultureInfo.CurrentCulture, "Value read from data reader ('{0}') was too large to convert to type {1}.", + value, + conversionType)); + } + } + } +} \ No newline at end of file Index: Core/Common/src/Core.Common.IO/Readers/SqLiteDatabaseReaderBase.cs =================================================================== diff -u -re4565100f14feece0bea5bc7acf9eef9acf7a8e6 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Core/Common/src/Core.Common.IO/Readers/SqLiteDatabaseReaderBase.cs (.../SqLiteDatabaseReaderBase.cs) (revision e4565100f14feece0bea5bc7acf9eef9acf7a8e6) +++ Core/Common/src/Core.Common.IO/Readers/SqLiteDatabaseReaderBase.cs (.../SqLiteDatabaseReaderBase.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -20,6 +20,7 @@ // All rights reserved. using System; +using System.Data; using System.Data.SQLite; using System.IO; using Core.Common.IO.Exceptions; @@ -94,7 +95,7 @@ /// /// The to process. /// True if the command was successful and a new resultset is available, false otherwise. - protected static bool MoveNext(SQLiteDataReader sqliteDataReader) + protected static bool MoveNext(IDataReader sqliteDataReader) { return sqliteDataReader.Read() || (sqliteDataReader.NextResult() && sqliteDataReader.Read()); } @@ -106,7 +107,7 @@ /// Parameters the is dependend on. /// A new instance of . /// The execution of failed. - protected SQLiteDataReader CreateDataReader(string queryString, params SQLiteParameter[] parameters) + protected IDataReader CreateDataReader(string queryString, params SQLiteParameter[] parameters) { using (var query = new SQLiteCommand(Connection) { Index: Core/Common/test/Core.Common.IO.Test/Core.Common.IO.Test.csproj =================================================================== diff -u -r2d5e2d09b0cb1a7f48e1b0a067d332347c89d4a8 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Core/Common/test/Core.Common.IO.Test/Core.Common.IO.Test.csproj (.../Core.Common.IO.Test.csproj) (revision 2d5e2d09b0cb1a7f48e1b0a067d332347c89d4a8) +++ Core/Common/test/Core.Common.IO.Test/Core.Common.IO.Test.csproj (.../Core.Common.IO.Test.csproj) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -39,6 +39,10 @@ ..\..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll True + + ..\..\..\..\packages\RhinoMocks.3.6.1\lib\net\Rhino.Mocks.dll + True + @@ -51,12 +55,14 @@ Properties\GlobalAssembly.cs + + Index: Core/Common/test/Core.Common.IO.Test/Exceptions/ConversionExceptionTest.cs =================================================================== diff -u --- Core/Common/test/Core.Common.IO.Test/Exceptions/ConversionExceptionTest.cs (revision 0) +++ Core/Common/test/Core.Common.IO.Test/Exceptions/ConversionExceptionTest.cs (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -0,0 +1,114 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using Core.Common.IO.Exceptions; +using Core.Common.TestUtil; +using NUnit.Framework; + +namespace Core.Common.IO.Test.Exceptions +{ + [TestFixture] + public class ConversionExceptionTest + { + [Test] + [SetCulture("en-US")] + public void DefaultConstructor_ExpectedValues() + { + // Call + var exception = new ConversionException(); + + // Assert + Assert.IsInstanceOf(exception); + var expectedMessage = string.Format("Exception of type '{0}' was thrown.", exception.GetType()); + Assert.AreEqual(expectedMessage, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.IsNull(exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + + [Test] + public void MessageConstructor_ExpectedValues() + { + // Setup + const string messageText = ""; + + // Call + var exception = new ConversionException(messageText); + + // Assert + Assert.IsInstanceOf(exception); + Assert.AreEqual(messageText, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.IsNull(exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + + [Test] + public void MessageAndInnerExceptionConstructor_ExpectedValues() + { + // Setup + var innerException = new Exception(); + const string messageText = ""; + + // Call + var exception = new ConversionException(messageText, innerException); + + // Assert + Assert.IsInstanceOf(exception); + Assert.AreEqual(messageText, exception.Message); + CollectionAssert.IsEmpty(exception.Data); + Assert.IsNull(exception.HelpLink); + Assert.AreSame(innerException, exception.InnerException); + Assert.IsNull(exception.Source); + Assert.IsNull(exception.StackTrace); + Assert.IsNull(exception.TargetSite); + } + + [Test] + public void Constructor_SerializationRoundTrip_ExceptionProperlyInitialized() + { + // Setup + var originalInnerException = new Exception("inner"); + var originalException = new ConversionException("outer", originalInnerException); + + // Precondition + Assert.IsNotNull(originalException.InnerException); + Assert.IsNull(originalException.InnerException.InnerException); + + // Call + ConversionException persistedException = SerializationTestHelper.SerializeAndDeserializeException(originalException); + + // Assert + Assert.AreEqual(originalException.Message, persistedException.Message); + Assert.IsNotNull(persistedException.InnerException); + Assert.AreEqual(originalException.InnerException.GetType(), persistedException.InnerException.GetType()); + Assert.AreEqual(originalException.InnerException.Message, persistedException.InnerException.Message); + Assert.IsNull(persistedException.InnerException.InnerException); + } + } +} \ No newline at end of file Index: Core/Common/test/Core.Common.IO.Test/Readers/IDataReaderExtensionsTest.cs =================================================================== diff -u --- Core/Common/test/Core.Common.IO.Test/Readers/IDataReaderExtensionsTest.cs (revision 0) +++ Core/Common/test/Core.Common.IO.Test/Readers/IDataReaderExtensionsTest.cs (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -0,0 +1,149 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.Data; +using System.Globalization; +using Core.Common.IO.Exceptions; +using Core.Common.IO.Readers; +using NUnit.Framework; +using Rhino.Mocks; + +namespace Core.Common.IO.Test.Readers +{ + [TestFixture] + public class IDataReaderExtensionsTest + { + [Test] + public void Read_NullDataReader_ThrowsArgumentNullException() + { + // Call + TestDelegate test = () => ((IDataReader)null).Read("column"); + + // Assert + var paramName = Assert.Throws(test).ParamName; + Assert.AreEqual("dataReader", paramName); + } + + [Test] + public void Read_NullColumnName_ThrowsArgumentNullException() + { + // Setup + var mockRepository = new MockRepository(); + var dataReader = mockRepository.Stub(); + mockRepository.ReplayAll(); + + // Call + TestDelegate test = () => dataReader.Read(null); + + // Assert + var paramName = Assert.Throws(test).ParamName; + Assert.AreEqual("columnName", paramName); + + mockRepository.VerifyAll(); + } + + [Test] + public void Read_NumberWithInvalidFormat_ThrowsInvalidCastException() + { + // Setup + var mockRepository = new MockRepository(); + var dataReader = mockRepository.Stub(); + string columName = "SomeColumn"; + dataReader.Stub(dr => dr[columName]).Return("3..2"); + mockRepository.ReplayAll(); + + // Call + TestDelegate test = () => dataReader.Read(columName); + + // Assert + var message = Assert.Throws(test).Message; + Assert.AreEqual("Value read from data reader ('3..2') is an incorrect format to transform to type System.Int32.", message); + + mockRepository.VerifyAll(); + } + + [Test] + public void Read_UsingTypeNotMatchingColumnType_ThrowsInvalidCastException() + { + // Setup + var mockRepository = new MockRepository(); + var dataReader = mockRepository.Stub(); + string columName = "SomeColumn"; + var value = 3.9; + dataReader.Stub(dr => dr[columName]).Return(value); + mockRepository.ReplayAll(); + + // Call + TestDelegate test = () => dataReader.Read(columName); + + // Assert + var message = Assert.Throws(test).Message; + var expectedMessage = string.Format(CultureInfo.CurrentCulture, + "Value read from data reader ('{0}') could not be cast to desired type System.Data.IDataReader.", + value); + Assert.AreEqual(expectedMessage, message); + + mockRepository.VerifyAll(); + } + + [Test] + public void Read_ColumnValueTooLargeForUsedType_ThrowsInvalidCastException() + { + // Setup + var mockRepository = new MockRepository(); + var dataReader = mockRepository.Stub(); + string columName = "SomeColumn"; + dataReader.Stub(dr => dr[columName]).Return(3e139); + mockRepository.ReplayAll(); + + // Call + TestDelegate test = () => dataReader.Read(columName); + + // Assert + var message = Assert.Throws(test).Message; + Assert.AreEqual("Value read from data reader ('3E+139') was too large to convert to type System.Int32.", message); + + mockRepository.VerifyAll(); + } + + [Test] + public void Read_UsingSameTypeAsColumnType_ReturnsTypedValue() + { + // Setup + string columName = "SomeColumn"; + var testValue = "testValue"; + + var mockRepository = new MockRepository(); + var dataReader = mockRepository.Stub(); + dataReader.Stub(dr => dr[columName]).Return(testValue); + mockRepository.ReplayAll(); + + // Call + string result = dataReader.Read(columName); + + // Assert + Assert.AreEqual(testValue, result); + + mockRepository.VerifyAll(); + } + } +} \ No newline at end of file Index: Core/Common/test/Core.Common.IO.Test/packages.config =================================================================== diff -u -rfea3ed82dfb6dfcad535eef16efcbaa9c01564ed -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Core/Common/test/Core.Common.IO.Test/packages.config (.../packages.config) (revision fea3ed82dfb6dfcad535eef16efcbaa9c01564ed) +++ Core/Common/test/Core.Common.IO.Test/packages.config (.../packages.config) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -23,5 +23,6 @@ --> + \ No newline at end of file Index: Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/DesignTablesSettingsProvider.cs =================================================================== diff -u -r4b93743129a2c7335995686ba8ccbee63b476446 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/DesignTablesSettingsProvider.cs (.../DesignTablesSettingsProvider.cs) (revision 4b93743129a2c7335995686ba8ccbee63b476446) +++ Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/DesignTablesSettingsProvider.cs (.../DesignTablesSettingsProvider.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -64,6 +64,8 @@ /// The corresponding to the provided failure mechanism type and location id. /// Thrown when is not a valid /// value. + /// Thrown when a column that is being read doesn't + /// contain expected type. public DesignTablesSetting GetDesignTablesSetting(long locationId, HydraRingFailureMechanismType failureMechanismType) { return designTableSettingsReader.ReadDesignTableSetting(locationId, failureMechanismType) ?? Index: Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/HydraRingSettingsDatabaseReader.cs =================================================================== diff -u -r4b93743129a2c7335995686ba8ccbee63b476446 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/HydraRingSettingsDatabaseReader.cs (.../HydraRingSettingsDatabaseReader.cs) (revision 4b93743129a2c7335995686ba8ccbee63b476446) +++ Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/HydraRingSettingsDatabaseReader.cs (.../HydraRingSettingsDatabaseReader.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -24,6 +24,7 @@ using System.ComponentModel; using System.Data; using System.Data.SQLite; +using System.Linq; using Core.Common.IO.Exceptions; using Core.Common.IO.Readers; using Ringtoets.Common.IO.Properties; @@ -133,6 +134,8 @@ /// A new containing values read from the database. /// Thrown when is not a valid /// value. + /// Thrown when a column that is being read doesn't + /// contain expected type. public DesignTablesSetting ReadDesignTableSetting(long locationId, HydraRingFailureMechanismType calculationType) { if (!Enum.IsDefined(calculationType.GetType(), calculationType)) @@ -144,9 +147,16 @@ { if (MoveNext(reader)) { - return new DesignTablesSetting( - Convert.ToDouble(reader[minColumn]), - Convert.ToDouble(reader[maxColumn])); + try + { + return new DesignTablesSetting( + reader.Read(minColumn), + reader.Read(maxColumn)); + } + catch (ConversionException) + { + throw new CriticalFileReadException(Resources.HydraRingSettingsDatabaseReader_ValidateSchema_Hydraulic_calculation_settings_database_has_invalid_schema); + } } } return null; @@ -159,27 +169,36 @@ /// The mechanism id to obtain the for. /// The sub mechanism id to obtain the for. /// A new containing values read from the database. + /// Thrown when a column that is being read doesn't + /// contain expected type. public NumericsSetting ReadNumericsSetting(long locationId, int mechanismId, int subMechanismId) { using (var reader = CreateNumericsSettingsDataReader(locationId, mechanismId, subMechanismId)) { if (MoveNext(reader)) { - return new NumericsSetting( - Convert.ToInt32(reader[calculationTechniqueIdColumn]), - Convert.ToInt32(reader[formStartMethodColumn]), - Convert.ToInt32(reader[formNumberOfIterationsColumn]), - Convert.ToDouble(reader[formRelaxationFactorColumn]), - Convert.ToDouble(reader[formEpsBetaColumn]), - Convert.ToDouble(reader[formEpsHohColumn]), - Convert.ToDouble(reader[formEpsZFuncColumn]), - Convert.ToInt32(reader[dsStartMethodColumn]), - Convert.ToInt32(reader[dsMinNumberOfIterationsColumn]), - Convert.ToInt32(reader[dsMaxNumberOfIterationsColumn]), - Convert.ToDouble(reader[dsVarCoefficientColumn]), - Convert.ToDouble(reader[niUMinColumn]), - Convert.ToDouble(reader[niUMaxColumn]), - Convert.ToInt32(reader[niNumberStepsColumn])); + try + { + return new NumericsSetting( + reader.Read(calculationTechniqueIdColumn), + reader.Read(formStartMethodColumn), + reader.Read(formNumberOfIterationsColumn), + reader.Read(formRelaxationFactorColumn), + reader.Read(formEpsBetaColumn), + reader.Read(formEpsHohColumn), + reader.Read(formEpsZFuncColumn), + reader.Read(dsStartMethodColumn), + reader.Read(dsMinNumberOfIterationsColumn), + reader.Read(dsMaxNumberOfIterationsColumn), + reader.Read(dsVarCoefficientColumn), + reader.Read(niUMinColumn), + reader.Read(niUMaxColumn), + reader.Read(niNumberStepsColumn)); + } + catch (ConversionException) + { + throw new CriticalFileReadException(Resources.HydraRingSettingsDatabaseReader_ValidateSchema_Hydraulic_calculation_settings_database_has_invalid_schema); + } } } return null; @@ -193,6 +212,8 @@ /// A new containing values read from the database. /// Thrown when is not a valid /// value. + /// Thrown when a column that is being read doesn't + /// contain expected type. public TimeIntegrationSetting ReadTimeIntegrationSetting(long locationId, HydraRingFailureMechanismType calculationType) { if (!Enum.IsDefined(calculationType.GetType(), calculationType)) @@ -204,7 +225,15 @@ { if (MoveNext(reader)) { - return new TimeIntegrationSetting(Convert.ToInt32(reader[timeIntegrationSchemeIdColumn])); + try + { + return new TimeIntegrationSetting( + reader.Read(timeIntegrationSchemeIdColumn)); + } + catch (ConversionException) + { + throw new CriticalFileReadException(Resources.HydraRingSettingsDatabaseReader_ValidateSchema_Hydraulic_calculation_settings_database_has_invalid_schema); + } } } return null; @@ -214,18 +243,39 @@ /// Reads the excluded locations (those for which no calculation is possible) from the database. /// /// A of ids for all the excluded locations. + /// Thrown when a column that is being read doesn't + /// contain expected type. public IEnumerable ReadExcludedLocations() { using (var reader = CreateExcludedLocationsDataReader()) { while (MoveNext(reader)) { - yield return Convert.ToInt64(reader[locationIdColumn]); + yield return TryReadLocationIdColumn(reader); } } } /// + /// Tries to read the from the . + /// + /// The reader to read the column's value from. + /// The id of the location that was read from the . + /// Thrown when the + /// column contains a value of unexpected type. + private long TryReadLocationIdColumn(IDataReader reader) + { + try + { + return reader.Read(locationIdColumn); + } + catch (ConversionException) + { + throw new CriticalFileReadException(Resources.HydraRingSettingsDatabaseReader_ValidateSchema_Hydraulic_calculation_settings_database_has_invalid_schema); + } + } + + /// /// Verifies that the schema of the opened settings database is valid. /// /// Thrown when the @@ -241,17 +291,10 @@ private bool ContainsRequiredTables(List> definitions) { - foreach (var tableDefinition in GetValidSchema()) - { - if (!definitions.Contains(tableDefinition)) - { - return false; - } - } - return true; + return GetValidSchema().All(tableDefinition => definitions.Contains(tableDefinition)); } - private SQLiteDataReader CreateDesignTablesDataReader(long locationId, HydraRingFailureMechanismType calculationType) + private IDataReader CreateDesignTablesDataReader(long locationId, HydraRingFailureMechanismType calculationType) { var locationParameter = new SQLiteParameter { @@ -273,7 +316,7 @@ typeParameter); } - private SQLiteDataReader CreateNumericsSettingsDataReader(long locationId, int mechanismId, int subMechanismId) + private IDataReader CreateNumericsSettingsDataReader(long locationId, int mechanismId, int subMechanismId) { var locationParameter = new SQLiteParameter { @@ -303,7 +346,7 @@ subMechanismIdParameter); } - private SQLiteDataReader CreateTimeIntegrationDataReader(long locationId, HydraRingFailureMechanismType calculationType) + private IDataReader CreateTimeIntegrationDataReader(long locationId, HydraRingFailureMechanismType calculationType) { var locationParameter = new SQLiteParameter { @@ -325,7 +368,7 @@ typeParameter); } - private SQLiteDataReader CreateExcludedLocationsDataReader() + private IDataReader CreateExcludedLocationsDataReader() { return CreateDataReader(excludedLocationsQuery); } Index: Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/HydraulicBoundaryLocationFilter.cs =================================================================== diff -u -r49c5da81f49a23dd6e66526d264a08bf510e6963 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/HydraulicBoundaryLocationFilter.cs (.../HydraulicBoundaryLocationFilter.cs) (revision 49c5da81f49a23dd6e66526d264a08bf510e6963) +++ Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/HydraulicBoundaryLocationFilter.cs (.../HydraulicBoundaryLocationFilter.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -45,6 +45,7 @@ /// The contains invalid characters. /// No file could be found at . /// Unable to open database file. + /// Unable to read required data from database file. /// /// public HydraulicBoundaryLocationFilter(string databaseFilePath) Index: Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/NumericsSettingsProvider.cs =================================================================== diff -u -r382a89069b631e11752a6fabf9b80b9274c8503e -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/NumericsSettingsProvider.cs (.../NumericsSettingsProvider.cs) (revision 382a89069b631e11752a6fabf9b80b9274c8503e) +++ Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/NumericsSettingsProvider.cs (.../NumericsSettingsProvider.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using Core.Common.IO.Exceptions; using Ringtoets.HydraRing.Calculation.Data; using Ringtoets.HydraRing.Calculation.Data.Settings; @@ -63,6 +64,10 @@ /// The to obtain the for. /// A new where the key is the submechanism id, and the value is /// the containing values corresponding to the provided failure mechanism type and location id. + /// Thrown when is not a valid + /// value. + /// Thrown when a column that is being read doesn't + /// contain expected type. public Dictionary GetNumericsSettings(long locationId, HydraRingFailureMechanismType failureMechanismType) { var failureMechanismDefaults = new FailureMechanismDefaultsProvider().GetFailureMechanismDefaults(failureMechanismType); Index: Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/TimeIntegrationSettingsProvider.cs =================================================================== diff -u -r382a89069b631e11752a6fabf9b80b9274c8503e -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/TimeIntegrationSettingsProvider.cs (.../TimeIntegrationSettingsProvider.cs) (revision 382a89069b631e11752a6fabf9b80b9274c8503e) +++ Ringtoets/Common/src/Ringtoets.Common.IO/HydraRing/TimeIntegrationSettingsProvider.cs (.../TimeIntegrationSettingsProvider.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -20,6 +20,7 @@ // All rights reserved. using System; +using System.ComponentModel; using Core.Common.IO.Exceptions; using Ringtoets.HydraRing.Calculation.Data; using Ringtoets.HydraRing.Calculation.Data.Settings; @@ -57,6 +58,10 @@ /// The location id to obtain the for. /// The to obtain the for. /// The corresponding to the provided failure mechanism type and location id. + /// Thrown when is not a valid + /// value. + /// Thrown when a column that is being read doesn't + /// contain expected type. public TimeIntegrationSetting GetTimeIntegrationSetting(long locationId, HydraRingFailureMechanismType failureMechanismType) { return timeIntegrationSettingsReader.ReadTimeIntegrationSetting(locationId, failureMechanismType) ?? Index: Ringtoets/Common/src/Ringtoets.Common.Service/HydraRingSettingsDatabaseHelper.cs =================================================================== diff -u -rb66269d1c3435557b993a5daa333612017f6ccfd -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Common/src/Ringtoets.Common.Service/HydraRingSettingsDatabaseHelper.cs (.../HydraRingSettingsDatabaseHelper.cs) (revision b66269d1c3435557b993a5daa333612017f6ccfd) +++ Ringtoets/Common/src/Ringtoets.Common.Service/HydraRingSettingsDatabaseHelper.cs (.../HydraRingSettingsDatabaseHelper.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -46,6 +46,7 @@ /// No settings database file could be found at the location of /// with the same name. /// Unable to open settings database file. + /// Unable to read required data from database file. /// /// public static void AssignSettingsFromDatabase(HydraRingCalculationInput calculationInput, string hydraulicBoundaryDatabaseFilePath) Index: Ringtoets/Common/test/Ringtoets.Common.IO.Test/HydraRing/HydraRingSettingsDatabaseReaderTest.cs =================================================================== diff -u -r382a89069b631e11752a6fabf9b80b9274c8503e -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Common/test/Ringtoets.Common.IO.Test/HydraRing/HydraRingSettingsDatabaseReaderTest.cs (.../HydraRingSettingsDatabaseReaderTest.cs) (revision 382a89069b631e11752a6fabf9b80b9274c8503e) +++ Ringtoets/Common/test/Ringtoets.Common.IO.Test/HydraRing/HydraRingSettingsDatabaseReaderTest.cs (.../HydraRingSettingsDatabaseReaderTest.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -22,10 +22,12 @@ using System.Collections.Generic; using System.ComponentModel; using System.IO; +using System.Linq; using Core.Common.IO.Exceptions; using Core.Common.IO.Readers; using Core.Common.TestUtil; using NUnit.Framework; +using Ringtoets.Common.Data.TestUtil; using Ringtoets.Common.IO.HydraRing; using Ringtoets.HydraRing.Calculation.Data; using Ringtoets.HydraRing.Calculation.Data.Settings; @@ -45,6 +47,10 @@ TestDataPath.Ringtoets.Common.IO, Path.Combine(testDataSubDirectory, "7_67-empty.config.sqlite")); + private static readonly string invalidDatabasePath = TestHelper.GetTestDataPath( + TestDataPath.Ringtoets.Common.IO, + Path.Combine(testDataSubDirectory, "7_67-invalid-value-types.config.sqlite")); + private static readonly string invalidSchemaDatabasePath = TestHelper.GetTestDataPath( TestDataPath.Ringtoets.Common.IO, Path.Combine(testDataSubDirectory, "invalid-settings-schema.config.sqlite")); @@ -140,6 +146,22 @@ } [Test] + [TestCase(700131, 5)] + [TestCase(700132, 0)] + public void ReadDesignTableSetting_InvalidValueInReadLocation_ThrowsCriticalFileReadException(long locationId, HydraRingFailureMechanismType type) + { + // Setup + using (var reader = new HydraRingSettingsDatabaseReader(invalidDatabasePath)) + { + // Call + TestDelegate test = () => reader.ReadDesignTableSetting(locationId, type); + + // Assert + Assert.Throws(test); + } + } + + [Test] [TestCase(-1)] [TestCase(12)] [TestCase(15)] @@ -157,6 +179,20 @@ } [Test] + public void ReadTimeIntegrationSetting_InvalidValueInReadLocation_ThrowsCriticalFileReadException() + { + // Setup + using (var reader = new HydraRingSettingsDatabaseReader(invalidDatabasePath)) + { + // Call + TestDelegate test = () => reader.ReadTimeIntegrationSetting(700131, HydraRingFailureMechanismType.AssessmentLevel); + + // Assert + Assert.Throws(test); + } + } + + [Test] [TestCase(700131, 0, 1)] [TestCase(700131, 3, 1)] [TestCase(700134, 2, 1)] @@ -271,6 +307,35 @@ } [Test] + [TestCase(700132, 11, 14)] + [TestCase(700133, 11, 14)] + [TestCase(700134, 11, 14)] + [TestCase(700135, 11, 14)] + [TestCase(700136, 11, 14)] + [TestCase(700137, 11, 14)] + [TestCase(700138, 11, 14)] + [TestCase(700139, 11, 14)] + [TestCase(700140, 1, 1)] + [TestCase(700141, 1, 1)] + [TestCase(700142, 1, 1)] + [TestCase(700143, 1, 1)] + [TestCase(700144, 1, 1)] + [TestCase(700145, 1, 1)] + public void ReadNumericsSetting_InvalidValueInReadLocation_ThrowsCriticalFileReadException( + long locationId, int mechanismId, int subMechanismId) + { + // Setup + using (var reader = new HydraRingSettingsDatabaseReader(invalidDatabasePath)) + { + // Call + TestDelegate test = () => reader.ReadNumericsSetting(locationId, mechanismId, subMechanismId); + + // Assert + Assert.Throws(test); + } + } + + [Test] public void ReadNumericsSetting_EmptyTable_ReturnNull() { // Setup @@ -305,6 +370,20 @@ } [Test] + public void ReadExcludedLocations_InvalidValueInReadLocation_ThrowsCriticalFileReadException() + { + // Setup + using (var reader = new HydraRingSettingsDatabaseReader(invalidDatabasePath)) + { + // Call + TestDelegate test = () => reader.ReadExcludedLocations().ToArray(); + + // Assert + Assert.Throws(test); + } + } + + [Test] public void ReadExcludedLocations_EmptyTable_ReturnsEmptyList() { // Setup Index: Ringtoets/Common/test/Ringtoets.Common.IO.Test/test-data/HydraRingSettingsDatabaseReader/7_67-invalid-value-types.config.sqlite =================================================================== diff -u Binary files differ Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicBoundaryDatabaseContext/HydraulicBoundarySqLiteDatabaseReader.cs =================================================================== diff -u -re4565100f14feece0bea5bc7acf9eef9acf7a8e6 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicBoundaryDatabaseContext/HydraulicBoundarySqLiteDatabaseReader.cs (.../HydraulicBoundarySqLiteDatabaseReader.cs) (revision e4565100f14feece0bea5bc7acf9eef9acf7a8e6) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicBoundaryDatabaseContext/HydraulicBoundarySqLiteDatabaseReader.cs (.../HydraulicBoundarySqLiteDatabaseReader.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -36,7 +36,7 @@ /// public class HydraulicBoundarySqLiteDatabaseReader : SqLiteDatabaseReaderBase { - private SQLiteDataReader sqliteDataReader; + private IDataReader sqliteDataReader; /// /// Creates a new instance of , @@ -104,7 +104,7 @@ string versionQuery = HydraulicBoundaryDatabaseQueryBuilder.GetVersionQuery(); try { - using (SQLiteDataReader dataReader = CreateDataReader(versionQuery, null)) + using (IDataReader dataReader = CreateDataReader(versionQuery, null)) { return !dataReader.Read() ? string.Empty : Convert.ToString(dataReader[GeneralTableDefinitions.GeneratedVersion]); } @@ -133,7 +133,7 @@ }; try { - using (SQLiteDataReader dataReader = CreateDataReader(trackQuery, sqliteParameter)) + using (IDataReader dataReader = CreateDataReader(trackQuery, sqliteParameter)) { return !dataReader.Read() ? 0 : Convert.ToInt64(dataReader[GeneralTableDefinitions.TrackId]); } @@ -166,7 +166,7 @@ try { - using (SQLiteDataReader dataReader = CreateDataReader(locationCountQuery, sqliteParameter)) + using (IDataReader dataReader = CreateDataReader(locationCountQuery, sqliteParameter)) { return !dataReader.Read() ? 0 : Convert.ToInt32(dataReader[HrdLocationsTableDefinitions.Count]); } Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReader.cs =================================================================== diff -u -rfef3460a27a37aaa34948649aae3dd9ae143041c -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReader.cs (.../HydraulicLocationConfigurationSqLiteDatabaseReader.cs) (revision fef3460a27a37aaa34948649aae3dd9ae143041c) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReader.cs (.../HydraulicLocationConfigurationSqLiteDatabaseReader.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -88,7 +88,7 @@ { var dictionary = new Dictionary(); var locationIdQuery = HydraulicLocationConfigurationDatabaseQueryBuilder.GetLocationsIdByTrackIdQuery(); - using (SQLiteDataReader dataReader = CreateDataReader(locationIdQuery, trackParameter)) + using (IDataReader dataReader = CreateDataReader(locationIdQuery, trackParameter)) { while (MoveNext(dataReader)) { Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/PipingSoilProfileReader.cs =================================================================== diff -u -rad11d25e651c47162ecf08d11a05d40bba0bebca -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision ad11d25e651c47162ecf08d11a05d40bba0bebca) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -41,7 +41,7 @@ private const string pipingMechanismName = "Piping"; private const string mechanismParameterName = "mechanism"; - private SQLiteDataReader dataReader; + private IDataReader dataReader; /// /// Creates a new instance of which will use the Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/SoilDatabaseVersionReader.cs =================================================================== diff -u -re7e22e69b16b23c89c063f18444c82aa818dc176 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/SoilDatabaseVersionReader.cs (.../SoilDatabaseVersionReader.cs) (revision e7e22e69b16b23c89c063f18444c82aa818dc176) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/SoilDatabaseVersionReader.cs (.../SoilDatabaseVersionReader.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -79,9 +79,9 @@ private void ReadVersion(string checkVersionQuery, SQLiteParameter sqliteParameter) { - using (SQLiteDataReader dataReader = CreateDataReader(checkVersionQuery, sqliteParameter)) + using (IDataReader dataReader = CreateDataReader(checkVersionQuery, sqliteParameter)) { - if (!dataReader.HasRows) + if (!dataReader.Read()) { throw new CriticalFileReadException(string.Format( Resources.PipingSoilProfileReader_Database_incorrect_version_requires_Version_0_, Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/StochasticSoilModelReader.cs =================================================================== diff -u -rce31448a066c084f755439f3e7d453bfb042b291 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/StochasticSoilModelReader.cs (.../StochasticSoilModelReader.cs) (revision ce31448a066c084f755439f3e7d453bfb042b291) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/StochasticSoilModelReader.cs (.../StochasticSoilModelReader.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -40,7 +40,7 @@ { private const string pipingMechanismName = "Piping"; private readonly string filePath; - private SQLiteDataReader dataReader; + private IDataReader dataReader; /// /// Creates a new instance of , Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/StochasticSoilProfileReader.cs =================================================================== diff -u -r973ed43129e04e3bf314d654b5a9ff877f08f175 -rd73c509c93f18a87da76086c871eca2a2c903e12 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/StochasticSoilProfileReader.cs (.../StochasticSoilProfileReader.cs) (revision 973ed43129e04e3bf314d654b5a9ff877f08f175) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/StochasticSoilProfileReader.cs (.../StochasticSoilProfileReader.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) @@ -20,6 +20,7 @@ // All rights reserved. using System; +using System.Data; using System.Data.SQLite; using Core.Common.IO.Exceptions; using Core.Common.IO.Readers; @@ -38,7 +39,7 @@ /// public class StochasticSoilProfileReader : SqLiteDatabaseReaderBase { - private SQLiteDataReader dataReader; + private IDataReader dataReader; /// /// Creates a new instance of ,