#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab 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. * * HeuristicLab 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 HeuristicLab. If not, see . */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.Linq; using System.Diagnostics; using System.Linq; using System.Reflection; using System.ServiceModel; using HeuristicLab.Services.OKB.AttributeSelection; using HeuristicLab.Services.OKB.DataAccess; namespace HeuristicLab.Services.OKB { /// /// Implementation of the . /// [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, IncludeExceptionDetailInFaults = true)] public class TableService : ITableService, IDisposable { private static List SupportedTypes = new List() { typeof(int), typeof(long), typeof(double), typeof(string), typeof(Guid), typeof(DateTime?) }; private DataTable tableTemplate; private IEnumerable properties; private IEnumerator rowEnumerator; #region ITableService Members /// /// Updates the data table. /// /// The updated rows. /// Name of the table. public void UpdateDataTable(DataTable updatedRows, string tableName) { Type tableType = Assembly.GetAssembly(typeof(Run)).GetType("HeuristicLab.Services.OKB.DataAccess." + tableName, true); var properties = from p in tableType.GetProperties() where SupportedTypes.Contains(p.PropertyType) select p; using (OKBDataContext okb = new OKBDataContext()) { ITable table = okb.GetTable(tableType); foreach (DataRow row in updatedRows.Rows) { if (row["Id"] == DBNull.Value) table.InsertOnSubmit(CreateEntity(tableType, properties, row)); } var updated = updatedRows.Rows.Cast().Where(row => row["Id"] != DBNull.Value).OrderBy(row => row["Id"]); var entities = DataSetBuilder.GetEntities(okb, tableType, updated.Select(u => (int)u["Id"])); var updateEnum = updated.GetEnumerator(); var entityEnum = entities.GetEnumerator(); while (updateEnum.MoveNext() && entityEnum.MoveNext()) { bool idChecked = false; foreach (var property in properties) { Console.WriteLine("{0}.{1} = '{2}' -> '{3}'", tableName, property.Name, property.GetGetMethod().Invoke(entityEnum.Current, new object[0]), updateEnum.Current[property.Name]); if (property.Name == "Id") { int entityId = (int)property.GetGetMethod().Invoke(entityEnum.Current, new object[0]); int updateId = (int)updateEnum.Current["Id"]; Debug.Assert(entityId == updateId); idChecked = true; } object newValue = updateEnum.Current[property.Name]; if (newValue != DBNull.Value) property.GetSetMethod().Invoke(entityEnum.Current, new object[] { newValue }); } Debug.Assert(idChecked); } okb.SubmitChanges(); } } private object CreateEntity(Type tableType, IEnumerable properties, DataRow row) { object instance = Activator.CreateInstance(tableType); bool empty = true; foreach (var property in properties) { if (row[property.Name] != DBNull.Value) { property.GetSetMethod().Invoke(instance, new object[] { row[property.Name] }); Console.WriteLine("{0}.{1} = '{2}'", tableType.Name, property.Name, row[property.Name]); empty = false; } } if (empty) throw new ArgumentException("cannot create completely empty entity"); return instance; } /// /// Deletes the selected table rows using the value of the /// "Id" column. /// /// The ids. /// Name of the table. public void DeleteTableRows(int[] ids, string tableName) { Type tableType = Assembly.GetAssembly(typeof(Run)).GetType("HeuristicLab.Services.OKB.DataAccess" + tableName, true); using (OKBDataContext okb = new OKBDataContext()) { ITable table = okb.GetTable(tableType); table.DeleteAllOnSubmit(DataSetBuilder.GetEntities(okb, tableType, ids)); okb.SubmitChanges(); } } /// /// Prepares the data table to be downloaded. /// /// Name of the table. /// The number of rows. /// /// An empyt that contains just /// the column headers. /// public DataTable PrepareDataTable(string tableName, out int count) { Type tableType = Assembly.GetAssembly(typeof(Run)).GetType("HeuristicLab.Services.OKB.DataAccess." + tableName, true); properties = from p in tableType.GetProperties() where SupportedTypes.Contains(p.PropertyType) select p; tableTemplate = new DataTable(tableName); foreach (var property in properties) { Type type = property.PropertyType; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) type = type.GetGenericArguments()[0]; DataColumn column = new DataColumn(property.Name, type); if (type.Name == "Id") { column.ReadOnly = true; } tableTemplate.Columns.Add(column); } using (OKBDataContext okb = new OKBDataContext()) { ITable table = okb.GetTable(tableType); rowEnumerator = table.GetEnumerator(); count = DataSetBuilder.CountEntities(new OKBDataContext(), tableType); return tableTemplate; } } /// /// Gets the next few rows. /// /// The maximum number of rows to return. /// /// A partial with the /// next few rows. /// public DataTable GetNextRows(int count) { DataTable dataTable = tableTemplate.Clone(); int i = 0; while (i < count && rowEnumerator.MoveNext()) { i++; DataRow row = dataTable.NewRow(); foreach (var property in properties) { row[property.Name] = property.GetGetMethod().Invoke(rowEnumerator.Current, new object[0]) ?? DBNull.Value; } dataTable.Rows.Add(row); } return dataTable; } /// /// Finishes fetching rows and closes the connection. /// public void FinishFetchingRows() { Dispose(); } #endregion #region IDisposable Members /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { tableTemplate = null; properties = null; } #endregion } }