Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Modeling.Database.SQLServerCompact/3.2/DatabaseService.cs @ 2591

Last change on this file since 2591 was 2571, checked in by mkommend, 15 years ago

corrected reopening of connection if no database exists (ticket #759)

File size: 16.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Reflection;
26
27using HeuristicLab.Core;
28using HeuristicLab.DataAnalysis;
29using HeuristicLab.Data;
30using System.Data.Linq;
31
32namespace HeuristicLab.Modeling.Database.SQLServerCompact {
33  public class DatabaseService : IModelingDatabase {
34    private readonly string fileName;
35
36    public DatabaseService(string fileName) {
37      this.fileName = fileName;
38      this.readOnly = false;
39
40    }
41    public DatabaseService(string fileName, bool readOnly)
42      : this(fileName) {
43      this.readOnly = readOnly;
44    }
45
46    private string ConnectionString {
47      get {
48        string connection = "Data Source =" + fileName + ";";
49        if (this.readOnly)
50          connection += "File Mode = Read Only; Temp Path =" + System.IO.Path.GetTempPath() + ";";
51        else
52          connection += "File Mode = Shared Read;";
53        return connection;
54      }
55    }
56
57    private bool readOnly;
58    public bool ReadOnly {
59      get { return this.readOnly; }
60      set {
61        if (ctx != null)
62          throw new InvalidOperationException("Could not change readonly attribute of DatabaseService because connection is opened.");
63        this.readOnly = value;
64      }
65    }
66
67    public void EmptyDatabase() {
68      ctx.Connection.Dispose();
69      ctx.DeleteDatabase();
70      Connect();
71      ctx.CreateDatabase();
72      Disconnect();
73    }
74
75    private ModelingDataContext ctx;
76    public void Connect() {
77      if (ctx != null)
78        Disconnect();
79
80      ctx = new ModelingDataContext(this.ConnectionString);
81      DataLoadOptions dlo = new DataLoadOptions();
82      dlo.LoadWith<ModelResult>(mr => mr.Result);
83      dlo.LoadWith<ModelMetaData>(mmd => mmd.MetaData);
84      dlo.LoadWith<InputVariableResult>(ir => ir.Variable);
85      dlo.LoadWith<InputVariableResult>(ir => ir.Result);
86      dlo.LoadWith<Model>(m => m.TargetVariable);
87      dlo.LoadWith<Model>(m => m.Algorithm);
88      ctx.LoadOptions = dlo;
89      //ctx.Log = System.Console.Out;
90
91      if (!ctx.DatabaseExists() && !this.ReadOnly)
92        ctx.CreateDatabase();
93      else
94        ctx.Connection.Open();
95    }
96
97    public void Disconnect() {
98      if (ctx == null)
99        return;
100      ctx.Connection.Close();
101      ctx.Connection.Dispose();
102      ctx.Dispose();
103      ctx = null;
104    }
105
106    public void Commit() {
107      if (ctx != null)
108        ctx.SubmitChanges();
109    }
110
111    private void CheckConnection() {
112      CheckConnection(false);
113    }
114
115    private void CheckConnection(bool writeEnabled) {
116      if (ctx == null)
117        throw new InvalidOperationException("Could not perform operation, when not connected to the database.");
118      if (writeEnabled && this.ReadOnly)
119        throw new InvalidOperationException("Could not perform update operation, when database is in readonly mode.");
120    }
121
122    public IEnumerable<IModel> GetAllModels() {
123      this.CheckConnection();
124      return ctx.Models.ToList().Cast<IModel>();
125    }
126
127    public IEnumerable<int> GetAllModelIds() {
128      this.CheckConnection();
129      return from m in ctx.Models
130             select m.Id;
131    }
132
133    public IEnumerable<IVariable> GetAllVariables() {
134      this.CheckConnection();
135      return ctx.Variables.ToList().Cast<IVariable>();
136    }
137
138    public IEnumerable<IResult> GetAllResults() {
139      this.CheckConnection();
140      return ctx.Results.ToList().Cast<IResult>();
141    }
142
143    public IEnumerable<IResult> GetAllResultsForInputVariables() {
144      this.CheckConnection();
145      return (from ir in ctx.InputVariableResults select ir.Result).Distinct().ToList().Cast<IResult>();
146    }
147
148    public IEnumerable<IMetaData> GetAllMetaData() {
149      this.CheckConnection();
150      return ctx.MetaData.ToList().Cast<IMetaData>();
151    }
152
153    public IEnumerable<IAlgorithm> GetAllAlgorithms() {
154      this.CheckConnection();
155      return ctx.Algorithms.ToList().Cast<IAlgorithm>();
156    }
157
158    public IModel CreateModel(int id, string modelName, ModelType modelType, IAlgorithm algorithm, IVariable targetVariable,
159        int trainingSamplesStart, int trainingSamplesEnd, int validationSamplesStart, int validationSamplesEnd, int testSamplesStart, int testSamplesEnd) {
160      Model m = (Model)CreateModel(modelName, modelType, algorithm, targetVariable, trainingSamplesStart, trainingSamplesEnd, validationSamplesStart, validationSamplesEnd, testSamplesStart, testSamplesEnd);
161      m.Id = id;
162      return m;
163    }
164
165    public IModel CreateModel(string modelName, ModelType modelType, IAlgorithm algorithm, IVariable targetVariable,
166     int trainingSamplesStart, int trainingSamplesEnd, int validationSamplesStart, int validationSamplesEnd, int testSamplesStart, int testSamplesEnd) {
167      Variable target = (Variable)targetVariable;
168      Algorithm algo = (Algorithm)algorithm;
169      Model model = new Model(target, algo, modelType);
170      model.Name = modelName;
171      model.TrainingSamplesStart = trainingSamplesStart;
172      model.TrainingSamplesEnd = trainingSamplesEnd;
173      model.ValidationSamplesStart = validationSamplesStart;
174      model.ValidationSamplesEnd = validationSamplesEnd;
175      model.TestSamplesStart = testSamplesStart;
176      model.TestSamplesEnd = testSamplesEnd;
177
178      return model;
179    }
180
181    public IModel GetModel(int id) {
182      this.CheckConnection();
183      var model = ctx.Models.Where(m => m.Id == id);
184      if (model.Count() == 1)
185        return model.Single();
186      return null;
187    }
188
189    public void PersistModel(IModel model) {
190      this.CheckConnection(true);
191      Model m = (Model)model;
192      //check if model has to be updated or inserted
193      if (ctx.Models.Any(x => x.Id == model.Id)) {
194        Model orginal = ctx.Models.GetOriginalEntityState(m);
195        if (orginal == null)
196          ctx.Models.Attach(m);
197        ctx.Refresh(RefreshMode.KeepCurrentValues, m);
198      } else
199        ctx.Models.InsertOnSubmit(m);
200    }
201
202    public void DeleteModel(IModel model) {
203      this.CheckConnection(true);
204      Model m = (Model)model;
205      ctx.ModelData.DeleteAllOnSubmit(ctx.ModelData.Where(x => x.Model == m));
206      ctx.ModelMetaData.DeleteAllOnSubmit(ctx.ModelMetaData.Where(x => x.Model == m));
207      ctx.ModelResults.DeleteAllOnSubmit(ctx.ModelResults.Where(x => x.Model == m));
208      ctx.InputVariableResults.DeleteAllOnSubmit(ctx.InputVariableResults.Where(x => x.Model == m));
209      ctx.InputVariables.DeleteAllOnSubmit(ctx.InputVariables.Where(x => x.Model == m));
210      Model orginal = ctx.Models.GetOriginalEntityState(m);
211      if (orginal == null)
212        ctx.Models.Attach(m);
213      ctx.Models.DeleteOnSubmit(m);
214      ctx.SubmitChanges();
215    }
216
217    public Dataset GetDataset() {
218      this.CheckConnection();
219      if (ctx.Problems.Count() > 1)
220        throw new InvalidOperationException("Could not get dataset. More than one problems are persisted in the database.");
221      if (ctx.Problems.Count() == 1)
222        return ctx.Problems.Single().Dataset;
223      return null;
224    }
225
226    public void PersistProblem(Dataset dataset) {
227      this.CheckConnection(true);
228      Problem problem;
229      if (ctx.Problems.Count() != 0)
230        throw new InvalidOperationException("Could not persist dataset. A dataset is already saved in the database.");
231      problem = new Problem(dataset);
232      ctx.Problems.InsertOnSubmit(problem);
233      foreach (string variable in dataset.VariableNames) {
234        ctx.Variables.InsertOnSubmit(new Variable(variable));
235      }
236    }
237
238    public IVariable GetVariable(string variableName) {
239      this.CheckConnection();
240      var variables = ctx.Variables.Where(v => v.Name == variableName);
241      if (variables.Count() != 1)
242        throw new ArgumentException("Zero or more than one variable with the name " + variableName + " are persisted in the database.");
243      return variables.Single();
244    }
245
246    public IPredictor GetModelPredictor(IModel model) {
247      this.CheckConnection();
248      var data = (from md in ctx.ModelData
249                  where md.Model == model
250                  select md);
251      if (data.Count() != 1)
252        throw new ArgumentException("No predictor persisted for given model!");
253      return (IPredictor)PersistenceManager.RestoreFromGZip(data.Single().Data);
254    }
255
256    public void PersistPredictor(IModel model, IPredictor predictor) {
257      this.CheckConnection(true);
258      Model m = (Model)model;
259      ctx.ModelData.DeleteAllOnSubmit(ctx.ModelData.Where(x => x.Model == m));
260      ctx.ModelResults.DeleteAllOnSubmit(ctx.ModelResults.Where(x => x.Model == m));
261      ctx.InputVariableResults.DeleteAllOnSubmit(ctx.InputVariableResults.Where(x => x.Model == m));
262      ctx.InputVariables.DeleteAllOnSubmit(ctx.InputVariables.Where(x => x.Model == m));
263
264      ctx.ModelData.InsertOnSubmit(new ModelData(m, PersistenceManager.SaveToGZip(predictor)));
265      foreach (string variableName in predictor.GetInputVariables())
266        ctx.InputVariables.InsertOnSubmit(new InputVariable(m, (Variable)GetVariable(variableName)));
267    }
268
269    public IInputVariable GetInputVariable(IModel model, string inputVariableName) {
270      this.CheckConnection();
271      var inputVariables = ctx.InputVariables.Where(i => i.Model == model && i.Variable.Name == inputVariableName);
272      if (inputVariables.Count() == 1)
273        return inputVariables.Single();
274
275      if (inputVariables.Count() > 1)
276        throw new ArgumentException("More than one input variable with the same name are for the given model persisted.");
277
278      return null;
279    }
280
281    public IAlgorithm GetOrPersistAlgorithm(string algorithmName) {
282      this.CheckConnection();
283      Algorithm algorithm;
284      var algorithms = ctx.Algorithms.Where(algo => algo.Name == algorithmName);
285      if (algorithms.Count() == 0) {
286        algorithm = new Algorithm(algorithmName, "");
287        this.CheckConnection(true);
288        ctx.Algorithms.InsertOnSubmit(algorithm);
289        ctx.SubmitChanges();
290      } else if (algorithms.Count() == 1)
291        algorithm = algorithms.Single();
292      else
293        throw new ArgumentException("Could not get Algorithm. More than one algorithm with the name " + algorithmName + " are saved in database.");
294      return algorithm;
295    }
296
297    public IResult GetOrPersistResult(string resultName) {
298      this.CheckConnection();
299      Result result;
300      var results = ctx.Results.Where(r => r.Name == resultName);
301      if (results.Count() == 0) {
302        this.CheckConnection(true);
303        result = new Result(resultName);
304        ctx.Results.InsertOnSubmit(result);
305        ctx.SubmitChanges();
306      } else if (results.Count() == 1)
307        result = results.Single();
308      else
309        throw new ArgumentException("Could not get result. More than one result with the name " + resultName + " are saved in database.");
310      return result;
311    }
312
313    public IMetaData GetOrPersistMetaData(string metaDataName) {
314      this.CheckConnection();
315      MetaData metadata;
316      var md = ctx.MetaData.Where(r => r.Name == metaDataName);
317      if (md.Count() == 0) {
318        this.CheckConnection(true);
319        metadata = new MetaData(metaDataName);
320        ctx.MetaData.InsertOnSubmit(metadata);
321        ctx.SubmitChanges();
322      } else if (md.Count() == 1)
323        metadata = md.Single();
324      else
325        throw new ArgumentException("Could not get metadata. More than one metadata with the name " + metaDataName + " are saved in database.");
326      return metadata;
327    }
328
329    public IEnumerable<IModelResult> GetModelResults(IModel model) {
330      this.CheckConnection();
331      return ctx.ModelResults.Where(mr => mr.Model == model).Cast<IModelResult>();
332    }
333    public IEnumerable<IInputVariableResult> GetInputVariableResults(IModel model) {
334      this.CheckConnection();
335      return ctx.InputVariableResults.Where(ivr => ivr.Model == model).Cast<IInputVariableResult>();
336    }
337    public IEnumerable<IModelMetaData> GetModelMetaData(IModel model) {
338      this.CheckConnection();
339      return ctx.ModelMetaData.Where(md => md.Model == model).Cast<IModelMetaData>();
340    }
341
342    public IModelResult CreateModelResult(IModel model, IResult result, double value) {
343      Model m = (Model)model;
344      Result r = (Result)result;
345      return new ModelResult(m, r, value);
346    }
347
348    public void PersistModelResults(IModel model, IEnumerable<IModelResult> modelResults) {
349      this.CheckConnection(true);
350      ctx.ModelResults.DeleteAllOnSubmit(GetModelResults(model).Cast<ModelResult>());
351      ctx.ModelResults.InsertAllOnSubmit(modelResults.Cast<ModelResult>());
352    }
353
354    public IInputVariable CreateInputVariable(IModel model, IVariable variable) {
355      InputVariable inputVariable = new InputVariable((Model)model, (Variable)variable);
356      return inputVariable;
357    }
358
359    public IInputVariableResult CreateInputVariableResult(IInputVariable inputVariable, IResult result, double value) {
360      InputVariable i = (InputVariable)inputVariable;
361      Result r = (Result)result;
362      return new InputVariableResult(i, r, value);
363    }
364
365    public void PersistInputVariableResults(IModel model, IEnumerable<IInputVariableResult> inputVariableResults) {
366      this.CheckConnection(true);
367      ctx.InputVariableResults.DeleteAllOnSubmit(GetInputVariableResults(model).Cast<InputVariableResult>());
368      ctx.InputVariableResults.InsertAllOnSubmit(inputVariableResults.Cast<InputVariableResult>());
369    }
370
371    public IModelMetaData CreateModelMetaData(IModel model, IMetaData metadata, double value) {
372      Model m = (Model)model;
373      MetaData md = (MetaData)metadata;
374      return new ModelMetaData(m, md, value);
375    }
376
377    public void PersistModelMetaData(IModel model, IEnumerable<IModelMetaData> modelMetaData) {
378      this.CheckConnection(true);
379      ctx.ModelMetaData.DeleteAllOnSubmit(GetModelMetaData(model).Cast<ModelMetaData>());
380      ctx.ModelMetaData.InsertAllOnSubmit(modelMetaData.Cast<ModelMetaData>());
381    }
382
383    public void Persist(HeuristicLab.Modeling.IAnalyzerModel model, string algorithmName, string algorithmDescription) {
384      this.CheckConnection(true);
385      Algorithm algorithm = (Algorithm)GetOrPersistAlgorithm(algorithmName);
386      Variable targetVariable = (Variable)GetVariable(model.TargetVariable);
387      Model m = (Model)CreateModel(null, model.Type, algorithm, targetVariable, model.TrainingSamplesStart, model.TrainingSamplesEnd,
388        model.ValidationSamplesStart, model.ValidationSamplesEnd, model.TestSamplesStart, model.TestSamplesEnd);
389      ctx.Models.InsertOnSubmit(m);
390      ctx.SubmitChanges();
391      ctx.ModelData.InsertOnSubmit(new ModelData(m, PersistenceManager.SaveToGZip(model.Predictor)));
392
393      foreach (string variableName in model.Predictor.GetInputVariables())
394        ctx.InputVariables.InsertOnSubmit(new InputVariable(m, (Variable)GetVariable(variableName)));
395      ctx.SubmitChanges();
396
397      foreach (KeyValuePair<string, double> pair in model.MetaData) {
398        MetaData metaData = (MetaData)GetOrPersistMetaData(pair.Key);
399        ctx.ModelMetaData.InsertOnSubmit(new ModelMetaData(m, metaData, pair.Value));
400      }
401
402      foreach (KeyValuePair<ModelingResult, double> pair in model.Results) {
403        Result result = (Result)GetOrPersistResult(pair.Key.ToString());
404        ctx.ModelResults.InsertOnSubmit(new ModelResult(m, result, pair.Value));
405      }
406
407      foreach (InputVariable variable in ctx.InputVariables.Where(iv => iv.Model == m)) {
408        foreach (KeyValuePair<ModelingResult, double> variableResult in model.GetVariableResults(variable.Variable.Name)) {
409          Result result = (Result)GetOrPersistResult(variableResult.Key.ToString());
410          ctx.InputVariableResults.InsertOnSubmit(new InputVariableResult(variable, result, variableResult.Value));
411        }
412      }
413      ctx.SubmitChanges();
414    }
415  }
416}
Note: See TracBrowser for help on using the repository browser.