330 lines
9.8 KiB
C#
330 lines
9.8 KiB
C#
///
|
|
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using FluentNHibernate.Cfg;
|
|
using FluentNHibernate.Cfg.Db;
|
|
using log4net;
|
|
using NHibernate;
|
|
using NHibernate.Cfg;
|
|
using NHibernate.Tool.hbm2ddl;
|
|
using Results.Entities;
|
|
|
|
namespace Results
|
|
{
|
|
public static class DB
|
|
{
|
|
static readonly ILog log = LogManager.GetLogger(typeof(DB));
|
|
|
|
/// <summary> Session factory for all regular sessions, not for CreateEmptyResultsDB(). </summary>
|
|
public static ISessionFactory SessionFactory;
|
|
|
|
/// <summary> Connection string for all sessions </summary>
|
|
static string connectionString;
|
|
///
|
|
public static string ConnectionString
|
|
{
|
|
get { return connectionString; }
|
|
set
|
|
{
|
|
if (value != connectionString)
|
|
{
|
|
connectionString = value;
|
|
SessionFactory = null; /// Clear SessionFactory on connection string change
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary> Database type (MySQL or SQLite) for all sessions </summary>
|
|
private static Users.Entities.DBType dbType;
|
|
///
|
|
public static Users.Entities.DBType DbType
|
|
{
|
|
get { return dbType; }
|
|
set { dbType = value; SessionFactory = null; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// NHibernate session factory (to create the database session 'SessionFactory')
|
|
/// </summary>
|
|
/// <returns>A database session</returns>
|
|
static ISessionFactory CreateSessionFactory()
|
|
{
|
|
return CreateSessionFactory(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// NHibernate session factory (to create the database session 'SessionFactory')
|
|
/// </summary>
|
|
/// <param name="createDB">true = Create a new DB, false = Regular DB</param>
|
|
/// <returns>A database session</returns>
|
|
public static ISessionFactory CreateSessionFactory(bool createDB)
|
|
{
|
|
FluentConfiguration cfg = Fluently.Configure();
|
|
|
|
switch (dbType)
|
|
{
|
|
default:
|
|
case Users.Entities.DBType.MySql:
|
|
cfg = cfg.Database(MySQLConfiguration.Standard.ConnectionString(connectionString));
|
|
break;
|
|
case Users.Entities.DBType.SQLite:
|
|
cfg = cfg.Database(SQLiteConfiguration.Standard.UsingFile(connectionString));
|
|
break;
|
|
}
|
|
|
|
cfg = cfg.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Entities.WaterMeterData>());
|
|
|
|
if (createDB)
|
|
{
|
|
return cfg.ExposeConfiguration(BuildSchemaCreate).BuildSessionFactory();
|
|
}
|
|
else
|
|
{
|
|
return cfg.ExposeConfiguration(BuildSchema).BuildSessionFactory();
|
|
}
|
|
}
|
|
|
|
static void BuildSchema(Configuration config)
|
|
{
|
|
/// This NHibernate tool takes a configuration with mapping info and exports a database schema
|
|
new SchemaExport(config).SetOutputFile("db_schema");
|
|
}
|
|
|
|
static void BuildSchemaCreate(Configuration config)
|
|
{
|
|
/// This NHibernate tool takes a configuration with mapping info and exports a database schema
|
|
new SchemaExport(config).Create(true, true);
|
|
}
|
|
|
|
/// Create a NHibernate session for the given database
|
|
public static ISession CreateSession()
|
|
{
|
|
if (string.IsNullOrEmpty(connectionString))
|
|
{
|
|
throw new Exception("Connection string was not specified");
|
|
}
|
|
|
|
if (SessionFactory == null) SessionFactory = CreateSessionFactory();
|
|
|
|
return SessionFactory.OpenSession();
|
|
}
|
|
|
|
|
|
public static void SaveObject(object obj)
|
|
{
|
|
SaveObject(CreateSession(), obj);
|
|
}
|
|
///
|
|
public static void SaveObject(ISession session, object obj)
|
|
{
|
|
using (var transaction = session.BeginTransaction())
|
|
{
|
|
session.SaveOrUpdate(obj);
|
|
try { transaction.Commit(); }
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
|
|
public static void DeleteObject(object obj)
|
|
{
|
|
DeleteObject(CreateSession(), obj);
|
|
}
|
|
///
|
|
public static void DeleteObject(ISession session, object obj)
|
|
{
|
|
using (var transaction = session.BeginTransaction())
|
|
{
|
|
session.Delete(obj);
|
|
transaction.Commit();
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Create an empty users database.
|
|
/// Database contains only the user 'admin' and the control board component 'CB'.
|
|
/// </summary>
|
|
/// <param name="dbType">DBType.SQLite or DBType.MySql</param>
|
|
/// <param name="connectionString">Connection string</param>
|
|
/// <returns>true=success, false=error</returns>
|
|
public static bool CreateEmptyDB()
|
|
{
|
|
ISessionFactory sessionFactory = CreateSessionFactory(true);
|
|
if (sessionFactory == null) return false;
|
|
|
|
/// Populate the database
|
|
using (var session = sessionFactory.OpenSession())
|
|
{
|
|
using (var transaction = session.BeginTransaction())
|
|
{
|
|
transaction.Commit();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Shared data
|
|
/// </summary>
|
|
public static IList<Entities.TestData> TestDataList;
|
|
public static IList<Entities.Components> ComponentsList;
|
|
public static IList<Entities.WaterMeterData> WaterMeterDataList;
|
|
|
|
|
|
/// <summary>
|
|
/// Loads shared data from the database
|
|
/// </summary>
|
|
/// <exception>Throws NHibernate exceptions</exception>
|
|
public static void LoadSharedData()
|
|
{
|
|
ISession session = DB.CreateSession();
|
|
|
|
TestDataList = session.QueryOver<TestData>().List();
|
|
ComponentsList = session.QueryOver<Components>().List();
|
|
WaterMeterDataList = session.QueryOver<WaterMeterData>().List();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads shared data from the database
|
|
/// </summary>
|
|
/// <exception>Throws NHibernate exceptions</exception>
|
|
public static int GetMaxSavedBatchNr()
|
|
{
|
|
ISession session = DB.CreateSession();
|
|
IList<Entities.Batch> batches = session.QueryOver<Batch>().List();
|
|
|
|
int maxBatchNr = 0;
|
|
foreach (var b in batches)
|
|
{
|
|
if (b.BatchNr > maxBatchNr) maxBatchNr = b.BatchNr;
|
|
}
|
|
return maxBatchNr;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Update TestData, Components and WaterMeterData fo tests and water meters in batch results
|
|
/// with existing data in static lists TestDataList, ComponentsList and WaterMeterDataList.
|
|
/// </summary>
|
|
/// <param name="batch">Batch results</param>
|
|
/// <returns>true when any data modiifed</returns>
|
|
public static bool UpdateBatchData(Entities.Batch batch)
|
|
{
|
|
ISession session = DB.CreateSession();
|
|
|
|
if (session == null) return false;
|
|
|
|
foreach (var tr in batch.TestRslts)
|
|
{
|
|
/// Search in TestDataList and update test data in the new batch
|
|
TestData td = TestData.UpdateList(TestDataList, tr.TestData);
|
|
tr.TestData = td;
|
|
|
|
/// Search in ComponentsList and update components in the new batch
|
|
Components cd = Components.UpdateList(ComponentsList, tr.Components);
|
|
tr.Components = cd;
|
|
}
|
|
|
|
foreach (var wm in batch.WaterMeters)
|
|
{
|
|
/// Search in WaterMeterDataList and update water meter data in the new batch
|
|
WaterMeterData wmd = WaterMeterData.UpdateList(WaterMeterDataList, wm.WaterMeterData);
|
|
wm.WaterMeterData = wmd;
|
|
}
|
|
|
|
return true; /// TODO: Really check for modifications
|
|
}
|
|
|
|
|
|
public static bool SaveNewBatch(Entities.Batch batch)
|
|
{
|
|
ISession session = DB.CreateSession();
|
|
if (session == null) return false;
|
|
|
|
TestDataList = session.QueryOver<TestData>().List();
|
|
ComponentsList = session.QueryOver<Components>().List();
|
|
WaterMeterDataList = session.QueryOver<WaterMeterData>().List();
|
|
|
|
UpdateBatchData(batch);
|
|
|
|
ITransaction transaction = session.BeginTransaction();
|
|
if (transaction == null) return false;
|
|
|
|
try
|
|
{
|
|
foreach (var td in TestDataList) if (td.Id == 0) session.SaveOrUpdate(td);
|
|
foreach (var cd in ComponentsList) if (cd.Id == 0) session.SaveOrUpdate(cd);
|
|
foreach (var wd in WaterMeterDataList) if (wd.Id == 0) session.SaveOrUpdate(wd);
|
|
|
|
log.Debug(batch.ToString(1));
|
|
foreach (var tstRslt in batch.TestRslts)
|
|
{
|
|
log.Debug(tstRslt.ToString(1));
|
|
}
|
|
|
|
session.SaveOrUpdate(batch);
|
|
|
|
transaction.Commit();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
transaction.Rollback();
|
|
|
|
log.FatalFormat("Saving results of batch #{0} into the results DB failed: {1}", batch.BatchNr, exc.Message);
|
|
if (exc.InnerException != null && !string.IsNullOrEmpty(exc.InnerException.Message))
|
|
{
|
|
log.FatalFormat("Inner exception message: {0}", exc.InnerException.Message);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
session.Flush();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
public static Batch LoadBatch(int batchNr)
|
|
{
|
|
IList<Batch> batches;
|
|
ISession session = DB.CreateSession();
|
|
if (session == null) return null;
|
|
|
|
try
|
|
{
|
|
TestDataList = session.QueryOver<TestData>().List();
|
|
ComponentsList = session.QueryOver<Components>().List();
|
|
WaterMeterDataList = session.QueryOver<WaterMeterData>().List();
|
|
|
|
batches = session.QueryOver<Batch>()
|
|
.Where(x => (x.BatchNr == batchNr))
|
|
.List();
|
|
|
|
foreach (var batch in batches)
|
|
{
|
|
batch.TestRslts = session.QueryOver<TestRslt>()
|
|
.Where(x => (x.Batch.Id == batch.Id))
|
|
.List();
|
|
|
|
batch.WaterMeters = session.QueryOver<WaterMeter>()
|
|
.Where(x => (x.Batch.Id == batch.Id))
|
|
.List();
|
|
}
|
|
|
|
return (batches.Count > 0) ? batches[0] : null;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
log.FatalFormat("Cannot load batch #{0}: {1}", batchNr, exc.Message);
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|