using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Data.SQLite; using System.IO; using System.Linq; using System.Xml; using Wti.Data; using Wti.IO.Builders; using Wti.IO.Exceptions; using Wti.IO.Properties; namespace Wti.IO { /// /// This class reads a SqLite database file and constructs from this database. /// The database is created with the DSoilModel application. /// public class PipingSoilProfileReader : IDisposable { private const int pipingMechanismId = 4; private const int profileNameIndex = 0; private const int profileLayerGeometryIndex = 1; private const int intersectionXIndex = 3; private SQLiteConnection connection; private SQLiteDataReader dataReader; /// /// Creates a new instance of which will use the /// as its source. /// /// public PipingSoilProfileReader(string dbFile) { if (String.IsNullOrEmpty(dbFile)) { throw new ArgumentException(Resources.Error_PathMustBeSpecified); } if (!File.Exists(dbFile)) { throw new FileNotFoundException(String.Format(Resources.Error_File_0_does_not_exist, dbFile)); } PrepareConnection(dbFile); Connect(); } /// /// Creates instances of based on the database file of the . /// /// /// Thrown when reading soil profile entries from the database failed. /// Thrown when parsing the geometry of a soil layer failed. public IEnumerable Read() { var pipingSoilProfiles = new Dictionary(); CreateDataReader(); while (dataReader.Read()) { var profileName = (string) dataReader[profileNameIndex]; var intersectionX = (double) dataReader[intersectionXIndex]; if (!pipingSoilProfiles.ContainsKey(profileName)) { pipingSoilProfiles.Add(profileName, new SoilProfileBuilder(profileName, intersectionX)); } pipingSoilProfiles[profileName].Add(ReadPipingSoilLayer()); } return pipingSoilProfiles.Select(keyValue => keyValue.Value.Build()); } public void Dispose() { dataReader.Dispose(); connection.Dispose(); } private void PrepareConnection(string dbFile) { var connectionStringBuilder = new SQLiteConnectionStringBuilder { FailIfMissing = true, DataSource = dbFile, ReadOnly = true, ForeignKeys = true }; connection = new SQLiteConnection(connectionStringBuilder.ConnectionString); } private void Connect() { try { connection.Open(); } catch (SQLiteException) { connection.Dispose(); } } private SoilLayer2D ReadPipingSoilLayer() { var columnValue = dataReader[profileLayerGeometryIndex]; var geometry = (byte[]) columnValue; return new PipingSoilLayer2DReader(geometry).Read(); } /// /// Creates a new data reader to use in this class, based on a query which returns all the known soil layers for which its profile has a X coordinate defined for piping. /// private void CreateDataReader() { var mechanismParameterName = "mechanism"; var query = new SQLiteCommand(connection) { CommandText = string.Format( "SELECT p.SP2D_Name, l.GeometrySurface, mat.MA_Name, mpl.X " + "FROM MechanismPointLocation as m " + "JOIN MechanismPointLocation as mpl ON m.ME_ID = mpl.ME_ID " + "JOIN SoilProfile2D as p ON m.SP2D_ID = p.SP2D_ID " + "JOIN SoilLayer2D as l ON l.SP2D_ID = p.SP2D_ID " + "JOIN Materials as mat ON mat.MA_ID = l.MA_ID " + "WHERE m.ME_ID = @{0} " + "ORDER BY p.SP2D_ID, l.SP2D_ID", mechanismParameterName) }; query.Parameters.Add(new SQLiteParameter { DbType = DbType.Int32, Value = pipingMechanismId, ParameterName = mechanismParameterName }); try { dataReader = query.ExecuteReader(); } catch (SQLiteException e) { throw new PipingSoilProfileReadException(string.Format(Resources.Error_SoilProfileReadFromDatabase, connection.DataSource), e); } } } }