Free cookie consent management tool by TermsFeed Policy Generator

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

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

added context usings to correct bug while persisting models (ticket #792)

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