Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Mainform refactoring/HeuristicLab.Modeling.Database.SQLServerCompact/3.2/DatabaseService.cs @ 2450

Last change on this file since 2450 was 2390, checked in by mkommend, 15 years ago

correctd bug in persistence of models (ticket #759)

File size: 15.4 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 connection;
35    public DatabaseService(string connection) {
36      this.connection = connection;
37      Connect();
38      if (!ctx.DatabaseExists())
39        ctx.CreateDatabase();
40    }
41
42    public void EmptyDatabase() {
43      ctx.Connection.Dispose();
44      ctx.DeleteDatabase();
45      Connect();
46      ctx.CreateDatabase();
47    }
48
49    private ModelingDataContext ctx;
50    public void Connect() {
51      if (ctx != null)
52        Disconnect();
53
54      ctx = new ModelingDataContext(connection);
55      DataLoadOptions dlo = new DataLoadOptions();
56      dlo.LoadWith<ModelResult>(mr => mr.Result);
57      dlo.LoadWith<ModelMetaData>(mmd => mmd.MetaData);
58      dlo.LoadWith<InputVariableResult>(ir => ir.Variable);
59      dlo.LoadWith<InputVariableResult>(ir => ir.Result);
60      dlo.LoadWith<Model>(m => m.TargetVariable);
61      dlo.LoadWith<Model>(m => m.Algorithm);
62      ctx.LoadOptions = dlo;
63    }
64
65    public void Disconnect() {
66      if (ctx == null)
67        return;
68      ctx.Connection.Dispose();
69      ctx.Dispose();
70      ctx = null;
71    }
72
73    public IEnumerable<IModel> GetAllModels() {
74      return ctx.Models.ToList().Cast<IModel>();
75    }
76
77    public IEnumerable<IVariable> GetAllVariables() {
78      return ctx.Variables.ToList().Cast<IVariable>();
79    }
80
81    public IEnumerable<IResult> GetAllResults() {
82      return ctx.Results.ToList().Cast<IResult>();
83    }
84
85    public IEnumerable<IResult> GetAllResultsForInputVariables() {
86      return (from ir in ctx.InputVariableResults select ir.Result).Distinct().ToList().Cast<IResult>();
87    }
88
89    public IEnumerable<IMetaData> GetAllMetaData() {
90      return ctx.MetaData.ToList().Cast<IMetaData>();
91    }
92
93    public IEnumerable<IAlgorithm> GetAllAlgorithms() {
94      return ctx.Algorithms.ToList().Cast<IAlgorithm>();
95    }
96
97    public IModel CreateModel(int id, string modelName, ModelType modelType, IAlgorithm algorithm, IVariable targetVariable,
98        int trainingSamplesStart, int trainingSamplesEnd, int validationSamplesStart, int validationSamplesEnd, int testSamplesStart, int testSamplesEnd) {
99      Model m = (Model)CreateModel(modelName, modelType, algorithm, targetVariable, trainingSamplesStart, trainingSamplesEnd, validationSamplesStart, validationSamplesEnd, testSamplesStart, testSamplesEnd);
100      m.Id = id;
101      return m;
102    }
103
104    public IModel CreateModel(string modelName, ModelType modelType, IAlgorithm algorithm, IVariable targetVariable,
105     int trainingSamplesStart, int trainingSamplesEnd, int validationSamplesStart, int validationSamplesEnd, int testSamplesStart, int testSamplesEnd) {
106      Variable target = (Variable)targetVariable;
107      Algorithm algo = (Algorithm)algorithm;
108      Model model = new Model(target, algo, modelType);
109      model.Name = modelName;
110      model.TrainingSamplesStart = trainingSamplesStart;
111      model.TrainingSamplesEnd = trainingSamplesEnd;
112      model.ValidationSamplesStart = validationSamplesStart;
113      model.ValidationSamplesEnd = validationSamplesEnd;
114      model.TestSamplesStart = testSamplesStart;
115      model.TestSamplesEnd = testSamplesEnd;
116
117      return model;
118    }
119
120    public void PersistModel(IModel model) {
121      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
122        Model m = (Model)model;
123        //check if model has to be updated or inserted
124        if (ctx.Models.Any(x => x.Id == model.Id)) {
125          Model orginal = ctx.Models.GetOriginalEntityState(m);
126          if (orginal == null)
127            ctx.Models.Attach(m);
128          ctx.Refresh(RefreshMode.KeepCurrentValues, m);
129        } else
130          ctx.Models.InsertOnSubmit(m);
131        ctx.SubmitChanges();
132      }
133    }
134
135    public void DeleteModel(IModel model) {
136      Model m = (Model)model;
137      ctx.ModelData.DeleteAllOnSubmit(ctx.ModelData.Where(x => x.Model == m));
138      ctx.ModelMetaData.DeleteAllOnSubmit(ctx.ModelMetaData.Where(x => x.Model == m));
139      ctx.ModelResults.DeleteAllOnSubmit(ctx.ModelResults.Where(x => x.Model == m));
140      ctx.InputVariableResults.DeleteAllOnSubmit(ctx.InputVariableResults.Where(x => x.Model == m));
141      ctx.InputVariables.DeleteAllOnSubmit(ctx.InputVariables.Where(x => x.Model == m));
142      Model orginal = ctx.Models.GetOriginalEntityState(m);
143      if (orginal == null)
144        ctx.Models.Attach(m);
145      ctx.Models.DeleteOnSubmit(m);
146      ctx.SubmitChanges();
147    }
148
149    public Dataset GetDataset() {
150      if (ctx.Problems.Count() > 1)
151        throw new InvalidOperationException("Could not get dataset. More than one problems are persisted in the database.");
152      if (ctx.Problems.Count() == 1)
153        return ctx.Problems.Single().Dataset;
154      return null;
155    }
156
157    public void PersistProblem(Dataset dataset) {
158      Problem problem;
159      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
160        if (ctx.Problems.Count() != 0)
161          throw new InvalidOperationException("Could not persist dataset. A dataset is already saved in the database.");
162        problem = new Problem(dataset);
163        ctx.Problems.InsertOnSubmit(problem);
164        foreach (string variable in dataset.VariableNames) {
165          ctx.Variables.InsertOnSubmit(new Variable(variable));
166        }
167        ctx.SubmitChanges();
168      }
169    }
170
171    public IVariable GetVariable(string variableName) {
172      var variables = ctx.Variables.Where(v => v.Name == variableName);
173      if (variables.Count() != 1)
174        throw new ArgumentException("Zero or more than one variable with the name " + variableName + " are persisted in the database.");
175      return variables.Single();
176    }
177
178    public IPredictor GetModelPredictor(IModel model) {
179      var data = (from md in ctx.ModelData
180                  where md.Model == model
181                  select md);
182      if (data.Count() != 1)
183        throw new ArgumentException("No predictor persisted for given model!");
184      return (IPredictor)PersistenceManager.RestoreFromGZip(data.Single().Data);
185    }
186
187    public void PersistPredictor(IModel model, IPredictor predictor) {
188      Model m = (Model)model;
189      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
190        ctx.ModelData.DeleteAllOnSubmit(ctx.ModelData.Where(x => x.Model == m));
191        ctx.ModelResults.DeleteAllOnSubmit(ctx.ModelResults.Where(x => x.Model == m));
192        ctx.InputVariableResults.DeleteAllOnSubmit(ctx.InputVariableResults.Where(x => x.Model == m));
193        ctx.InputVariables.DeleteAllOnSubmit(ctx.InputVariables.Where(x => x.Model == m));
194
195        ctx.ModelData.InsertOnSubmit(new ModelData(m, PersistenceManager.SaveToGZip(predictor)));
196        foreach (string variableName in predictor.GetInputVariables())
197          ctx.InputVariables.InsertOnSubmit(new InputVariable(m, (Variable)GetVariable(variableName)));
198
199        ctx.SubmitChanges();
200      }
201    }
202
203    public IInputVariable GetInputVariable(IModel model, string inputVariableName) {
204      var inputVariables = ctx.InputVariables.Where(i => i.Model == model && i.Variable.Name == inputVariableName);
205      if (inputVariables.Count() == 1)
206        return inputVariables.Single();
207
208      if (inputVariables.Count() > 1)
209        throw new ArgumentException("More than one input variable with the same name are for the given model persisted.");
210
211      return null;
212    }
213
214    public IAlgorithm GetOrPersistAlgorithm(string algorithmName) {
215      Algorithm algorithm;
216      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
217        var algorithms = ctx.Algorithms.Where(algo => algo.Name == algorithmName);
218        if (algorithms.Count() == 0) {
219          algorithm = new Algorithm(algorithmName, "");
220          ctx.Algorithms.InsertOnSubmit(algorithm);
221          ctx.SubmitChanges();
222        } else if (algorithms.Count() == 1)
223          algorithm = algorithms.Single();
224        else
225          throw new ArgumentException("Could not get Algorithm. More than one algorithm with the name " + algorithmName + " are saved in database.");
226      }
227      return algorithm;
228    }
229
230    public IResult GetOrPersistResult(string resultName) {
231      Result result;
232      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
233        var results = ctx.Results.Where(r => r.Name == resultName);
234        if (results.Count() == 0) {
235          result = new Result(resultName);
236          ctx.Results.InsertOnSubmit(result);
237          ctx.SubmitChanges();
238        } else if (results.Count() == 1)
239          result = results.Single();
240        else
241          throw new ArgumentException("Could not get result. More than one result with the name " + resultName + " are saved in database.");
242      }
243      return result;
244    }
245
246    public IMetaData GetOrPersistMetaData(string metaDataName) {
247      MetaData metadata;
248      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
249        var md = ctx.MetaData.Where(r => r.Name == metaDataName);
250        if (md.Count() == 0) {
251          metadata = new MetaData(metaDataName);
252          ctx.MetaData.InsertOnSubmit(metadata);
253          ctx.SubmitChanges();
254        } else if (md.Count() == 1)
255          metadata = md.Single();
256        else
257          throw new ArgumentException("Could not get metadata. More than one metadata with the name " + metaDataName + " are saved in database.");
258      }
259      return metadata;
260    }
261
262    public IEnumerable<IModelResult> GetModelResults(IModel model) {
263      return ctx.ModelResults.Where(mr => mr.Model == model).Cast<IModelResult>();
264    }
265    public IEnumerable<IInputVariableResult> GetInputVariableResults(IModel model) {
266      return ctx.InputVariableResults.Where(ivr => ivr.Model == model).Cast<IInputVariableResult>();
267    }
268    public IEnumerable<IModelMetaData> GetModelMetaData(IModel model) {
269      return ctx.ModelMetaData.Where(md => md.Model == model).Cast<IModelMetaData>();
270    }
271
272    public IModelResult CreateModelResult(IModel model, IResult result, double value) {
273      Model m = (Model)model;
274      Result r = (Result)result;
275      return new ModelResult(m, r, value);
276    }
277
278    public void PersistModelResults(IModel model, IEnumerable<IModelResult> modelResults) {
279      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
280        ctx.ModelResults.DeleteAllOnSubmit(GetModelResults(model).Cast<ModelResult>());
281        ctx.ModelResults.InsertAllOnSubmit(modelResults.Cast<ModelResult>());
282        ctx.SubmitChanges();
283      }
284    }
285
286    public IInputVariable CreateInputVariable(IModel model, IVariable variable) {
287      InputVariable inputVariable = new InputVariable((Model)model, (Variable)variable);
288      return inputVariable;
289    }
290
291    public IInputVariableResult CreateInputVariableResult(IInputVariable inputVariable, IResult result, double value) {
292      InputVariable i = (InputVariable)inputVariable;
293      Result r = (Result)result;
294      return new InputVariableResult(i, r, value);
295    }
296
297    public void PersistInputVariableResults(IModel model, IEnumerable<IInputVariableResult> inputVariableResults) {
298      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
299        ctx.InputVariableResults.DeleteAllOnSubmit(GetInputVariableResults(model).Cast<InputVariableResult>());
300        ctx.InputVariableResults.InsertAllOnSubmit(inputVariableResults.Cast<InputVariableResult>());
301        ctx.SubmitChanges();
302      }
303    }
304
305    public IModelMetaData CreateModelMetaData(IModel model, IMetaData metadata, double value) {
306      Model m = (Model)model;
307      MetaData md = (MetaData)metadata;
308      return new ModelMetaData(m, md, value);
309    }
310
311    public void PersistModelMetaData(IModel model, IEnumerable<IModelMetaData> modelMetaData) {
312      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
313        ctx.ModelMetaData.DeleteAllOnSubmit(GetModelMetaData(model).Cast<ModelMetaData>());
314        ctx.ModelMetaData.InsertAllOnSubmit(modelMetaData.Cast<ModelMetaData>());
315        ctx.SubmitChanges();
316      }
317    }
318
319    public IModel Persist(HeuristicLab.Modeling.IAlgorithm algorithm) {
320      if (ctx.Problems.Count() == 0)
321        PersistProblem(algorithm.Dataset);
322      return Persist(algorithm.Model, algorithm.Name, algorithm.Description);
323    }
324
325    public IModel Persist(HeuristicLab.Modeling.IAnalyzerModel model, string algorithmName, string algorithmDescription) {
326      Algorithm algorithm = (Algorithm)GetOrPersistAlgorithm(algorithmName);
327      Variable targetVariable = (Variable)GetVariable(model.TargetVariable);
328
329      Model m = (Model)CreateModel(null, model.Type, algorithm, targetVariable, model.TrainingSamplesStart, model.TrainingSamplesEnd,
330        model.ValidationSamplesStart, model.ValidationSamplesEnd, model.TestSamplesStart, model.TestSamplesEnd);
331      PersistModel(m);
332      PersistPredictor(m, model.Predictor);
333
334      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
335        foreach (KeyValuePair<string, double> pair in model.MetaData) {
336          MetaData metaData = (MetaData)GetOrPersistMetaData(pair.Key);
337          ctx.ModelMetaData.InsertOnSubmit(new ModelMetaData(m, metaData, pair.Value));
338        }
339        ctx.SubmitChanges();
340      }
341
342      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
343        foreach (KeyValuePair<ModelingResult, double> pair in model.Results) {
344          Result result = (Result)GetOrPersistResult(pair.Key.ToString());
345          ctx.ModelResults.InsertOnSubmit(new ModelResult(m, result, pair.Value));
346        }
347        ctx.SubmitChanges();
348      }
349
350      using (ModelingDataContext ctx = new ModelingDataContext(connection)) {
351        foreach (InputVariable variable in ctx.InputVariables.Where(iv => iv.Model == m)) {
352          foreach (KeyValuePair<ModelingResult, double> variableResult in model.GetVariableResults(variable.Variable.Name)) {
353            Result result = (Result)GetOrPersistResult(variableResult.Key.ToString());
354            ctx.InputVariableResults.InsertOnSubmit(new InputVariableResult(variable, result, variableResult.Value));
355          }
356        }
357        ctx.SubmitChanges();
358      }
359
360      //if connected to database return inserted model
361      if (this.ctx != null)
362        return this.ctx.Models.Where(x => x.Id == m.Id).Single();
363      return null;
364    }
365  }
366}
Note: See TracBrowser for help on using the repository browser.