Index: Core/Common/src/Core.Common.IO/Readers/SqLiteDatabaseReaderBase.cs =================================================================== diff -u -r7d124cef8960a865cc8d7db24b3359f7ff9958be -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Core/Common/src/Core.Common.IO/Readers/SqLiteDatabaseReaderBase.cs (.../SqLiteDatabaseReaderBase.cs) (revision 7d124cef8960a865cc8d7db24b3359f7ff9958be) +++ Core/Common/src/Core.Common.IO/Readers/SqLiteDatabaseReaderBase.cs (.../SqLiteDatabaseReaderBase.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -97,6 +97,38 @@ protected SQLiteConnection Connection { get; private set; } /// + /// Moves to and reads the next resultset in multiple row-returning SQL command. + /// + /// The to process. + /// True if the command was successful and a new resultset is available, false otherwise. + protected static bool MoveNext(SQLiteDataReader sqliteDataReader) + { + return sqliteDataReader.Read() || (sqliteDataReader.NextResult() && sqliteDataReader.Read()); + } + + /// + /// Creates a new , based upon and . + /// + /// The query to execute. + /// Parameters the is dependend on. + /// A new instance of . + /// The execution of failed. + protected SQLiteDataReader CreateDataReader(string queryString, params SQLiteParameter[] parameters) + { + using (var query = new SQLiteCommand(Connection) + { + CommandText = queryString + }) + { + if (parameters != null) + { + query.Parameters.AddRange(parameters); + } + return query.ExecuteReader(); + } + } + + /// /// Opens the connection with the . /// /// The database file to establish a connection with. Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicBoundaryDatabaseContext/HydraulicBoundarySqLiteDatabaseReader.cs =================================================================== diff -u -r7c7aa064bf7718dcdf9dc373f9eba77418cde957 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicBoundaryDatabaseContext/HydraulicBoundarySqLiteDatabaseReader.cs (.../HydraulicBoundarySqLiteDatabaseReader.cs) (revision 7c7aa064bf7718dcdf9dc373f9eba77418cde957) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicBoundaryDatabaseContext/HydraulicBoundarySqLiteDatabaseReader.cs (.../HydraulicBoundarySqLiteDatabaseReader.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -99,101 +99,90 @@ /// /// Gets the database version from the metadata table. /// - /// The version found in the database, or an empty string if the version + /// The version found in the database, or if the version /// cannot be found. - /// Thrown when the database returned incorrect - /// values for required properties. + /// Thrown when a query could not be executed on the database schema. public string GetVersion() { string versionQuery = HydraulicBoundaryDatabaseQueryBuilder.GetVersionQuery(); - var sqliteParameter = new SQLiteParameter + try { - DbType = DbType.String - }; - using (SQLiteDataReader dataReader = CreateDataReader(versionQuery, sqliteParameter)) - { - if (!dataReader.Read()) + using (SQLiteDataReader dataReader = CreateDataReader(versionQuery, null)) { - return ""; + return !dataReader.Read() ? String.Empty : Convert.ToString(dataReader[GeneralTableDefinitions.GeneratedVersion]); } - - try - { - return (string) dataReader[GeneralTableDefinitions.GeneratedVersion]; - } - catch (InvalidCastException e) - { - var message = new FileReaderErrorMessageBuilder(Path). - Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); - throw new LineParseException(message, e); - } } + catch (SQLiteException exception) + { + var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database); + throw new CriticalFileReadException(message, exception); + } } /// /// Gets the region id from the metadata table. /// /// The region id found in the database, or -1 if the region id /// cannot be found. - /// Thrown when the database returned incorrect + /// Thrown when the database returned incorrect /// values for required properties. + /// Thrown when a query could not be executed on the database schema. public int GetRegionId() { string versionQuery = HydraulicBoundaryDatabaseQueryBuilder.GetRegionIdQuery(); var sqliteParameter = new SQLiteParameter { DbType = DbType.String }; - using (SQLiteDataReader dataReader = CreateDataReader(versionQuery, sqliteParameter)) + try { - if (!dataReader.Read()) + using (SQLiteDataReader dataReader = CreateDataReader(versionQuery, sqliteParameter)) { - return -1; + return !dataReader.Read() ? 0 : Convert.ToInt32(dataReader[GeneralTableDefinitions.RegionId]); } - - try - { - return Convert.ToInt32(dataReader[GeneralTableDefinitions.RegionId]); - } - catch (InvalidCastException e) - { - var message = new FileReaderErrorMessageBuilder(Path). - Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); - throw new LineParseException(message, e); - } } + catch (InvalidCastException exception) + { + var message = new FileReaderErrorMessageBuilder(Path). + Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); + throw new LineParseException(message, exception); + } + catch (SQLiteException exception) + { + var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database); + throw new CriticalFileReadException(message, exception); + } } /// /// Gets the amount of locations that can be read from the database. /// - /// Thrown when the database returned incorrect - /// values for required properties. + /// The amount of locations that can be read. + /// Thrown when a query could not be executed on the database schema. public int GetLocationCount() { string locationCountQuery = HydraulicBoundaryDatabaseQueryBuilder.GetRelevantLocationsCountQuery(); var sqliteParameter = new SQLiteParameter { DbType = DbType.String }; - using (SQLiteDataReader dataReader = CreateDataReader(locationCountQuery, sqliteParameter)) + + try { - if (!dataReader.Read()) + using (SQLiteDataReader dataReader = CreateDataReader(locationCountQuery, sqliteParameter)) { - return 0; + return !dataReader.Read() ? 0 : Convert.ToInt32(dataReader[HrdLocationsTableDefinitions.Count]); } - - try - { - return Convert.ToInt32(dataReader[HrdLocationsTableDefinitions.Count]); - } - catch (InvalidCastException e) - { - var message = new FileReaderErrorMessageBuilder(Path). - Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); - throw new LineParseException(message, e); - } } + catch (InvalidCastException) + { + return 0; + } + catch (SQLiteException exception) + { + var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database); + throw new CriticalFileReadException(message, exception); + } } public override void Dispose() @@ -207,7 +196,7 @@ /// private void MoveNext() { - HasNext = sqliteDataReader.Read() || (sqliteDataReader.NextResult() && sqliteDataReader.Read()); + HasNext = MoveNext(sqliteDataReader); } /// @@ -247,37 +236,6 @@ } } - /// - /// Creates a new data reader to use in this class. - /// - /// Thrown when - /// - /// Amount of locations in database could not be read. - /// A query could not be executed on the database schema. - /// - /// - private SQLiteDataReader CreateDataReader(string queryString, params SQLiteParameter[] parameters) - { - using (var query = new SQLiteCommand(Connection) - { - CommandText = queryString - }) - { - query.Parameters.AddRange(parameters); - - try - { - return query.ExecuteReader(); - } - catch (SQLiteException exception) - { - Dispose(); - var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database); - throw new CriticalFileReadException(message, exception); - } - } - } - private void CloseDataReader() { if (sqliteDataReader != null) Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationDatabaseQueryBuilder.cs =================================================================== diff -u -r194139b3a9e8d221e69a4e5ff4adaa458eaedef5 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationDatabaseQueryBuilder.cs (.../HydraulicLocationConfigurationDatabaseQueryBuilder.cs) (revision 194139b3a9e8d221e69a4e5ff4adaa458eaedef5) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationDatabaseQueryBuilder.cs (.../HydraulicLocationConfigurationDatabaseQueryBuilder.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -29,18 +29,25 @@ public static class HydraulicLocationConfigurationDatabaseQueryBuilder { /// - /// Returns the query to get the LocationId from the database, based upon and . + /// Returns the query to get the LocationId from the database. /// /// The query to get the locationId from the database. - public static string GetLocationIdQuery(int regionId, int hrdLocationId) + public static string GetLocationIdQuery() { - return String.Format("SELECT {0} FROM {1} WHERE {2} = {3} AND {4} = {5};", + var countQuery = String.Format("Select COUNT({0}) FROM {1} WHERE {2} = @{2} AND {3} = @{3}", + LocationsTableDefinitions.LocationId, + LocationsTableDefinitions.TableName, + LocationsTableDefinitions.RegionId, + LocationsTableDefinitions.HrdLocationId); + + return String.Format("SELECT {0}, ({1}) as {2} FROM {3} WHERE {4} = @{4} AND {5} = @{5};", LocationsTableDefinitions.LocationId, + countQuery, + LocationsTableDefinitions.Count, LocationsTableDefinitions.TableName, LocationsTableDefinitions.RegionId, - hrdLocationId, - LocationsTableDefinitions.HrdLocationId, - regionId); + LocationsTableDefinitions.HrdLocationId + ); } } } \ No newline at end of file Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReader.cs =================================================================== diff -u --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReader.cs (revision 0) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReader.cs (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -0,0 +1,113 @@ +// 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 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 General Public License for more details. +// +// You should have received a copy of the GNU 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.Data.SQLite; +using Core.Common.IO.Exceptions; +using Core.Common.IO.Readers; +using Core.Common.Utils.Builders; +using log4net; +using Ringtoets.HydraRing.IO.Properties; + +namespace Ringtoets.HydraRing.IO.HydraulicLocationConfigurationDatabaseContext +{ + /// + /// This class reads an HLCD database file and reads location ids from this database. + /// + public class HydraulicLocationConfigurationSqLiteDatabaseReader : SqLiteDatabaseReaderBase + { + private static readonly ILog log = LogManager.GetLogger(typeof(HydraulicLocationConfigurationSqLiteDatabaseReader)); + + /// + /// Creates a new instance of , + /// which will use the as its source. + /// + /// The path of the database file to open. + /// Thrown when: + /// + /// The contains invalid characters. + /// No file could be found at . + /// + /// + public HydraulicLocationConfigurationSqLiteDatabaseReader(string databaseFilePath) : base(databaseFilePath) {} + + /// + /// Gets the location id from the database, based upon and . + /// + /// Hydraulic boundary region id. + /// Hydraulic boundary location id. + /// The location id found in the database, or 0 otherwise. + /// Thrown when the database query failed. + /// Thrown when the database returned incorrect values for + /// required properties. + public int GetLocationId(int regionId, int hrdLocationId) + { + var locationIdQuery = HydraulicLocationConfigurationDatabaseQueryBuilder.GetLocationIdQuery(); + var regionParameter = new SQLiteParameter + { + DbType = DbType.String, + ParameterName = LocationsTableDefinitions.RegionId, + Value = regionId + }; + var hrdLocationParameter = new SQLiteParameter + { + DbType = DbType.String, + ParameterName = LocationsTableDefinitions.HrdLocationId, + Value = hrdLocationId + }; + + try + { + return GetLocationIdFromDatabase(locationIdQuery, regionParameter, hrdLocationParameter); + } + catch (InvalidCastException exception) + { + var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); + throw new LineParseException(message, exception); + } + catch (SQLiteException exception) + { + var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.HydraulicLocationConfigurationSqLiteDatabaseReader_Critical_Unexpected_Exception); + throw new CriticalFileReadException(message, exception); + } + } + + private int GetLocationIdFromDatabase(string locationIdQuery, SQLiteParameter regionParameter, SQLiteParameter hrdLocationParameter) + { + using (SQLiteDataReader dataReader = CreateDataReader(locationIdQuery, regionParameter, hrdLocationParameter)) + { + if (!dataReader.Read()) + { + return 0; + } + var locationCount = Convert.ToInt32(dataReader[LocationsTableDefinitions.Count]); + + // Must be unique + if (locationCount > 1) + { + log.Warn(Resources.HydraulicLocationConfigurationSqLiteDatabaseReader_GetLocationIdFromDatabase_Ambiguous_Row_Found_Take_First); + } + return Convert.ToInt32(dataReader[LocationsTableDefinitions.LocationId]); + } + } + } +} \ No newline at end of file Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/LocationsTableDefinitions.cs =================================================================== diff -u -r194139b3a9e8d221e69a4e5ff4adaa458eaedef5 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/LocationsTableDefinitions.cs (.../LocationsTableDefinitions.cs) (revision 194139b3a9e8d221e69a4e5ff4adaa458eaedef5) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/HydraulicLocationConfigurationDatabaseContext/LocationsTableDefinitions.cs (.../LocationsTableDefinitions.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -31,5 +31,6 @@ internal const string LocationId = "LocationId"; internal const string HrdLocationId = "HRDLocationId"; internal const string RegionId = "RegionId"; + internal const string Count = "nrOfRows"; } } \ No newline at end of file Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Properties/Resources.Designer.cs =================================================================== diff -u -r3ba0c50f3a3548264d60e9f347079d0586c53f28 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 3ba0c50f3a3548264d60e9f347079d0586c53f28) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -77,5 +77,24 @@ return ResourceManager.GetString("HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column", resourceCulture); } } + + /// + /// Looks up a localized string similar to Het bevragen van de database is mislukt.. + /// + public static string HydraulicLocationConfigurationSqLiteDatabaseReader_Critical_Unexpected_Exception { + get { + return ResourceManager.GetString("HydraulicLocationConfigurationSqLiteDatabaseReader_Critical_Unexpected_Exception", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Er zijn meerdere resultaten gevonden, wat niet voor zou mogen komen. Neem contact op met de leverancier. Het eerste resultaat zal worden gebruikt.. + /// + public static string HydraulicLocationConfigurationSqLiteDatabaseReader_GetLocationIdFromDatabase_Ambiguous_Row_Found_Take_First { + get { + return ResourceManager.GetString("HydraulicLocationConfigurationSqLiteDatabaseReader_GetLocationIdFromDatabase_Ambi" + + "guous_Row_Found_Take_First", resourceCulture); + } + } } } Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Properties/Resources.resx =================================================================== diff -u -r7d124cef8960a865cc8d7db24b3359f7ff9958be -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Properties/Resources.resx (.../Resources.resx) (revision 7d124cef8960a865cc8d7db24b3359f7ff9958be) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Properties/Resources.resx (.../Resources.resx) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -123,4 +123,10 @@ Kritieke fout opgetreden bij het uitlezen van waardes uit kolommen in de database. + + Er zijn meerdere resultaten gevonden, wat niet voor zou mogen komen. Neem contact op met de leverancier. Het eerste resultaat zal worden gebruikt. + + + Het bevragen van de database is mislukt. + \ No newline at end of file Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Ringtoets.HydraRing.IO.csproj =================================================================== diff -u -r194139b3a9e8d221e69a4e5ff4adaa458eaedef5 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Ringtoets.HydraRing.IO.csproj (.../Ringtoets.HydraRing.IO.csproj) (revision 194139b3a9e8d221e69a4e5ff4adaa458eaedef5) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/Ringtoets.HydraRing.IO.csproj (.../Ringtoets.HydraRing.IO.csproj) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -34,6 +34,10 @@ AllRules.ruleset + + ..\..\..\..\packages\log4net.2.0.4\lib\net40-full\log4net.dll + True + @@ -51,6 +55,7 @@ + @@ -93,6 +98,7 @@ PublicResXFileCodeGenerator Resources.Designer.cs + Designer Index: Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/packages.config =================================================================== diff -u -r98fc85d8cecf9edae9fe7c1f2f47b60ecda5e187 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/packages.config (.../packages.config) (revision 98fc85d8cecf9edae9fe7c1f2f47b60ecda5e187) +++ Ringtoets/HydraRing/src/Ringtoets.HydraRing.IO/packages.config (.../packages.config) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -1,4 +1,5 @@  + \ No newline at end of file Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicBoundaryDatabaseContext/HydraulicBoundaryDatabaseReaderTest.cs =================================================================== diff -u -r7c7aa064bf7718dcdf9dc373f9eba77418cde957 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicBoundaryDatabaseContext/HydraulicBoundaryDatabaseReaderTest.cs (.../HydraulicBoundaryDatabaseReaderTest.cs) (revision 7c7aa064bf7718dcdf9dc373f9eba77418cde957) +++ Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicBoundaryDatabaseContext/HydraulicBoundaryDatabaseReaderTest.cs (.../HydraulicBoundaryDatabaseReaderTest.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; +using System.Data.SQLite; using System.IO; using Core.Common.IO.Exceptions; using Core.Common.IO.Readers; @@ -67,25 +68,48 @@ // Assert var exception = Assert.Throws(test); - Assert.AreEqual(expectedMessage, exception.Message); } [Test] - public void GetVersion_InvalidColumns_ThrowsLineParseException() + public void GetVersion_InvalidColumns_DoesNotThrowException() { // Setup var dbFile = Path.Combine(testDataPath, "corruptschema.sqlite"); - var expectedMessage = new FileReaderErrorMessageBuilder(dbFile).Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); // Precondition Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { + string version = "some version"; // Call + TestDelegate test = () => { version = hydraulicBoundarySqLiteDatabaseReader.GetVersion(); }; + + // Assert + Assert.DoesNotThrow(test); + Assert.AreEqual("Namedate", version); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] + public void GetVersion_EmptyDatabase_ThrowsCriticalFileReadException() + { + // Setup + var dbFile = Path.Combine(testDataPath, "empty.sqlite"); + string expectedException = new FileReaderErrorMessageBuilder(dbFile).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database); + + // Precondition + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); + using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) + { + // Call TestDelegate test = () => { hydraulicBoundarySqLiteDatabaseReader.GetVersion(); }; - var exception = Assert.Throws(test); - Assert.AreEqual(expectedMessage, exception.Message); + + // Assert + CriticalFileReadException exception = Assert.Throws(test); + Assert.AreEqual(expectedException, exception.Message); + Assert.IsInstanceOf(exception.InnerException); } Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); } @@ -99,6 +123,7 @@ // Call using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { + // Assert Assert.IsFalse(hydraulicBoundarySqLiteDatabaseReader.HasNext); } Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); @@ -108,29 +133,57 @@ public void GetLocationCount_ValidFile_ExpectedValues() { // Setup - const int nrOfLocations = 18; + const int expectedNrOfLocations = 18; var dbFile = Path.Combine(testDataPath, "complete.sqlite"); - // Call using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { - Assert.AreEqual(nrOfLocations, hydraulicBoundarySqLiteDatabaseReader.GetLocationCount()); + // Call + int nrOfLocations = hydraulicBoundarySqLiteDatabaseReader.GetLocationCount(); + + // Assert + Assert.AreEqual(expectedNrOfLocations, nrOfLocations); Assert.IsFalse(hydraulicBoundarySqLiteDatabaseReader.HasNext); } Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); } [Test] + public void GetLocationCount_EmptyDatabase_ThrowsCriticalFileReadException() + { + // Setup + var dbFile = Path.Combine(testDataPath, "empty.sqlite"); + string expectedException = new FileReaderErrorMessageBuilder(dbFile).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database); + + // Precondition + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); + using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) + { + // Call + TestDelegate test = () => { hydraulicBoundarySqLiteDatabaseReader.GetLocationCount(); }; + + // Assert + CriticalFileReadException exception = Assert.Throws(test); + Assert.AreEqual(expectedException, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] public void GetVersion_ValidFile_ExpectedValues() { // Setup - const string version = "Dutch coast South19-11-2015 12:00"; + const string expectedVersion = "Dutch coast South19-11-2015 12:00"; var dbFile = Path.Combine(testDataPath, "complete.sqlite"); - // Call using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { - Assert.AreEqual(version, hydraulicBoundarySqLiteDatabaseReader.GetVersion()); + // Call + string version = hydraulicBoundarySqLiteDatabaseReader.GetVersion(); + + // Assert + Assert.AreEqual(expectedVersion, version); Assert.IsFalse(hydraulicBoundarySqLiteDatabaseReader.HasNext); } Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); @@ -140,19 +193,67 @@ public void GetRegionId_ValidFile_ExpectedValues() { // Setup - const int version = 13; + const int expectedRegionId = 13; var dbFile = Path.Combine(testDataPath, "complete.sqlite"); - // Call using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { - Assert.AreEqual(version, hydraulicBoundarySqLiteDatabaseReader.GetRegionId()); + // Call + int regionId = hydraulicBoundarySqLiteDatabaseReader.GetRegionId(); + + // Assert + Assert.AreEqual(expectedRegionId, regionId); Assert.IsFalse(hydraulicBoundarySqLiteDatabaseReader.HasNext); } Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); } [Test] + public void GetRegionId_EmptyDatabase_ThrowsCriticalFileReadException() + { + // Setup + var dbFile = Path.Combine(testDataPath, "empty.sqlite"); + string expectedException = new FileReaderErrorMessageBuilder(dbFile).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database); + + // Precondition + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); + using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) + { + // Call + TestDelegate test = () => { hydraulicBoundarySqLiteDatabaseReader.GetRegionId(); }; + + // Assert + CriticalFileReadException exception = Assert.Throws(test); + Assert.AreEqual(expectedException, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] + public void GetRegionId_InvalidColumns_ThrowsLineParseException() + { + // Setup + var dbFile = Path.Combine(testDataPath, "corruptschema.sqlite"); + var expectedMessage = new FileReaderErrorMessageBuilder(dbFile).Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); + + // Precondition + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); + + using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) + { + // Call + TestDelegate test = () => hydraulicBoundarySqLiteDatabaseReader.GetRegionId(); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] public void ReadLocation_InvalidColumns_ThrowsLineParseException() { // Setup @@ -162,9 +263,9 @@ // Precondition Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); - // Call using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { + // Call hydraulicBoundarySqLiteDatabaseReader.PrepareReadLocation(); TestDelegate test = () => hydraulicBoundarySqLiteDatabaseReader.ReadLocation(); @@ -182,9 +283,9 @@ // Setup var dbFile = Path.Combine(testDataPath, "complete.sqlite"); - // Call using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { + // Call hydraulicBoundarySqLiteDatabaseReader.PrepareReadLocation(); HydraulicBoundaryLocation location = hydraulicBoundarySqLiteDatabaseReader.ReadLocation(); @@ -203,20 +304,20 @@ var boundaryLocations = new List(); CollectionAssert.IsEmpty(boundaryLocations); - // Call using (HydraulicBoundarySqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicBoundarySqLiteDatabaseReader(dbFile)) { + // Call hydraulicBoundarySqLiteDatabaseReader.PrepareReadLocation(); for (int i = 0; i < nrOfLocations; i++) { boundaryLocations.Add(hydraulicBoundarySqLiteDatabaseReader.ReadLocation()); } + // Assert Assert.IsFalse(hydraulicBoundarySqLiteDatabaseReader.HasNext); Assert.IsNull(hydraulicBoundarySqLiteDatabaseReader.ReadLocation()); } - // Assert CollectionAssert.AllItemsAreInstancesOfType(boundaryLocations, typeof(HydraulicBoundaryLocation)); Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); } Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationDatabaseQueryBuilderTest.cs =================================================================== diff -u -r194139b3a9e8d221e69a4e5ff4adaa458eaedef5 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationDatabaseQueryBuilderTest.cs (.../HydraulicLocationConfigurationDatabaseQueryBuilderTest.cs) (revision 194139b3a9e8d221e69a4e5ff4adaa458eaedef5) +++ Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationDatabaseQueryBuilderTest.cs (.../HydraulicLocationConfigurationDatabaseQueryBuilderTest.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -19,7 +19,6 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. -using System; using NUnit.Framework; using Ringtoets.HydraRing.IO.HydraulicLocationConfigurationDatabaseContext; @@ -29,15 +28,15 @@ public class HydraulicLocationConfigurationDatabaseQueryBuilderTest { [Test] - [TestCase(1, 2)] - [TestCase(18, 8537)] - public void GetLocationIdQuery_Always_ReturnsExpectedValues(int regionId, int hrdLocationId) + public void GetLocationIdQuery_Always_ReturnsExpectedValues() { // Setup - string expectedQuery = String.Format("SELECT LocationId FROM Locations WHERE RegionId = {0} AND HRDLocationId = {1};", hrdLocationId, regionId); + string expectedQuery = "SELECT LocationId, " + + "(Select COUNT(LocationId) FROM Locations WHERE RegionId = @RegionId AND HRDLocationId = @HRDLocationId) as nrOfRows " + + "FROM Locations WHERE RegionId = @RegionId AND HRDLocationId = @HRDLocationId;"; // Call - string query = HydraulicLocationConfigurationDatabaseQueryBuilder.GetLocationIdQuery(regionId, hrdLocationId); + string query = HydraulicLocationConfigurationDatabaseQueryBuilder.GetLocationIdQuery(); // Assert Assert.AreEqual(expectedQuery, query); Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReaderTest.cs =================================================================== diff -u --- Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReaderTest.cs (revision 0) +++ Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/HydraulicLocationConfigurationDatabaseContext/HydraulicLocationConfigurationSqLiteDatabaseReaderTest.cs (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -0,0 +1,164 @@ +// 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 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 General Public License for more details. +// +// You should have received a copy of the GNU 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.SQLite; +using System.IO; +using Core.Common.IO.Exceptions; +using Core.Common.IO.Readers; +using Core.Common.TestUtil; +using Core.Common.Utils.Builders; +using NUnit.Framework; +using Ringtoets.HydraRing.IO.HydraulicLocationConfigurationDatabaseContext; +using Ringtoets.HydraRing.IO.Properties; +using UtilsResources = Core.Common.Utils.Properties.Resources; + +namespace Ringtoets.HydraRing.IO.Test.HydraulicLocationConfigurationDatabaseContext +{ + [TestFixture] + public class HydraulicLocationConfigurationSqLiteDatabaseReaderTest + { + private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.HydraRing.IO, "HydraulicLocationConfigurationDatabase"); + + [Test] + public void Constructor_ValidFile_ThrowsCriticalFileReadException() + { + // Setup + var testFile = Path.Combine(testDataPath, "none.sqlite"); + var expectedMessage = new FileReaderErrorMessageBuilder(testFile).Build(UtilsResources.Error_File_does_not_exist); + + // Call + TestDelegate test = () => new HydraulicLocationConfigurationSqLiteDatabaseReader(testFile).Dispose(); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(expectedMessage, exception.Message); + } + + [Test] + public void Constructor_ValidFile_ExpectedValues() + { + // Setup + var dbFile = Path.Combine(testDataPath, "complete.sqlite"); + + // Call + using (HydraulicLocationConfigurationSqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicLocationConfigurationSqLiteDatabaseReader(dbFile)) + { + // Assert + Assert.IsInstanceOf(hydraulicBoundarySqLiteDatabaseReader); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] + [TestCase(1, 1, 100001)] + [TestCase(18, 1000, 1801000)] + [TestCase(6, 1000, 0)] + public void GetLocationId_ValidFile_ExpectedValues(int regionId, int hrdLocationId, int expectedLocationId) + { + // Setup + var dbFile = Path.Combine(testDataPath, "complete.sqlite"); + + using (HydraulicLocationConfigurationSqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicLocationConfigurationSqLiteDatabaseReader(dbFile)) + { + // Call + int locationId = hydraulicBoundarySqLiteDatabaseReader.GetLocationId(regionId, hrdLocationId); + + // Assert + Assert.AreEqual(expectedLocationId, locationId); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] + public void GetLocationId_AmbigousLocations_ReturnsFirstAndLogsWarning() + { + // Setup + var dbFile = Path.Combine(testDataPath, "ambigousLocation.sqlite"); + int regionId = 18; + int hrdLocationId = 1; + int expectedLocationId = 1800001; + string expectedMessage = "Er zijn meerdere resultaten gevonden, wat niet voor zou mogen komen. Neem contact op met de leverancier. Het eerste resultaat zal worden gebruikt."; + + using (HydraulicLocationConfigurationSqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicLocationConfigurationSqLiteDatabaseReader(dbFile)) + { + // Call + var locationId = -1; + Action call = () => locationId = hydraulicBoundarySqLiteDatabaseReader.GetLocationId(regionId, hrdLocationId); + + // Assert + TestHelper.AssertLogMessageIsGenerated(call, expectedMessage, 1); + Assert.AreEqual(expectedLocationId, locationId); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] + public void GetLocationId_InvalidColumns_ThrowsLineParseException() + { + // Setup + var dbFile = Path.Combine(testDataPath, "corruptschema.sqlite"); + var expectedMessage = new FileReaderErrorMessageBuilder(dbFile).Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column); + int regionId = 1; + int hrdLocationId = 1; + + // Precondition + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); + + using (HydraulicLocationConfigurationSqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicLocationConfigurationSqLiteDatabaseReader(dbFile)) + { + // Call + TestDelegate test = () => hydraulicBoundarySqLiteDatabaseReader.GetLocationId(regionId, hrdLocationId); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] + public void GetLocationId_EmptyFile_ThrowsCriticalFileReadException() + { + // Setup + var dbFile = Path.Combine(testDataPath, "empty.sqlite"); + var expectedMessage = new FileReaderErrorMessageBuilder(dbFile).Build(Resources.HydraulicLocationConfigurationSqLiteDatabaseReader_Critical_Unexpected_Exception); + int regionId = 1; + int hrdLocationId = 1; + + // Precondition + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); + + using (HydraulicLocationConfigurationSqLiteDatabaseReader hydraulicBoundarySqLiteDatabaseReader = new HydraulicLocationConfigurationSqLiteDatabaseReader(dbFile)) + { + // Call + TestDelegate test = () => hydraulicBoundarySqLiteDatabaseReader.GetLocationId(regionId, hrdLocationId); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + Assert.IsTrue(TestHelper.CanOpenFileForWrite(dbFile)); + } + } +} \ No newline at end of file Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/Ringtoets.HydraRing.IO.Test.csproj =================================================================== diff -u -r194139b3a9e8d221e69a4e5ff4adaa458eaedef5 -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/Ringtoets.HydraRing.IO.Test.csproj (.../Ringtoets.HydraRing.IO.Test.csproj) (revision 194139b3a9e8d221e69a4e5ff4adaa458eaedef5) +++ Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/Ringtoets.HydraRing.IO.Test.csproj (.../Ringtoets.HydraRing.IO.Test.csproj) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -46,6 +46,7 @@ + ..\..\..\..\packages\System.Data.SQLite.Core.1.0.99.0\lib\net40\System.Data.SQLite.dll True @@ -56,6 +57,7 @@ + Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/test-data/HydraulicBoundaryLocationReader/corruptschema.sqlite =================================================================== diff -u -rd5c512944b347df57c08bb0b281c9b764abe4a36 -r733d0d51adf737c52704cd80705507fdb34a2ba3 Binary files differ Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/test-data/HydraulicLocationConfigurationDatabase/ambigousLocation.sqlite =================================================================== diff -u Binary files differ Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/test-data/HydraulicLocationConfigurationDatabase/complete.sqlite =================================================================== diff -u Binary files differ Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/test-data/HydraulicLocationConfigurationDatabase/corruptschema.sqlite =================================================================== diff -u Binary files differ Index: Ringtoets/HydraRing/test/Ringtoets.HydraRing.IO.Test/test-data/HydraulicLocationConfigurationDatabase/empty.sqlite =================================================================== diff -u Binary files differ Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/PipingSoilProfileReader.cs =================================================================== diff -u -rb743d495d10779d51c8f75b7cb04b5babb4b226f -r733d0d51adf737c52704cd80705507fdb34a2ba3 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision b743d495d10779d51c8f75b7cb04b5babb4b226f) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision 733d0d51adf737c52704cd80705507fdb34a2ba3) @@ -111,7 +111,7 @@ /// public void MoveNext() { - HasNext = dataReader.Read() || (dataReader.NextResult() && dataReader.Read()); + HasNext = MoveNext(dataReader); } /// @@ -180,9 +180,28 @@ /// Prepares a new data reader with queries for obtaining the profiles and updates the reader /// so that it points to the first row of the result set. /// + /// Thrown when + /// + /// Version of the database does not match the required version. + /// Version of the database could not be read. + /// Amount of profiles in database could not be read. + /// + /// + /// A query could not be executed on the database schema. private void InitializeReader() { - PrepareReader(); + try + { + PrepareReader(); + CheckVersion(); + GetCount(); + } + catch (SQLiteException e) + { + Dispose(); + var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_SoilProfile_read_from_database); + throw new CriticalFileReadException(message, e); + } MoveNext(); } @@ -191,6 +210,7 @@ /// to take an intersection from. Since two separate queries are used, the will /// have two result sets which the method takes into account. /// + /// A query could not be executed on the database schema. private void PrepareReader() { string versionQuery = string.Format( @@ -322,7 +342,7 @@ layer2DPropertiesQuery, mechanismParameterName); - CreateDataReader(versionQuery + countQuery + query2D + query1D, new SQLiteParameter + dataReader = CreateDataReader(versionQuery + countQuery + query2D + query1D, new SQLiteParameter { DbType = DbType.String, Value = pipingMechanismName, @@ -331,41 +351,6 @@ } /// - /// Creates a new data reader to use in this class. - /// - /// Thrown when - /// - /// Version of the database doesn't match the required version. - /// Version of the database could not be read. - /// Amount of profiles in database could not be read. - /// A query could not be executed on the database schema. - /// - /// - private void CreateDataReader(string queryString, params SQLiteParameter[] parameters) - { - using (var query = new SQLiteCommand(Connection) - { - CommandText = queryString - }) - { - query.Parameters.AddRange(parameters); - - try - { - dataReader = query.ExecuteReader(); - CheckVersion(); - GetCount(); - } - catch (SQLiteException e) - { - Dispose(); - var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_SoilProfile_read_from_database); - throw new CriticalFileReadException(message, e); - } - } - } - - /// /// Checks the version read from the metadata table against the . /// /// Thrown when versions don't match.