Index: stable/HeuristicLab.Services.OKB/3.3/HeuristicLab.Services.OKB-3.3.csproj
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/HeuristicLab.Services.OKB-3.3.csproj	(revision 15081)
+++ stable/HeuristicLab.Services.OKB/3.3/HeuristicLab.Services.OKB-3.3.csproj	(revision 15082)
@@ -283,4 +283,6 @@
     <Compile Include="RunCreation\DataTransfer\BinaryValue.cs" />
     <Compile Include="RunCreation\DataTransfer\BoolValue.cs" />
+    <Compile Include="RunCreation\DataTransfer\SingleObjectiveSolution.cs" />
+    <Compile Include="RunCreation\DataTransfer\Solution.cs" />
     <Compile Include="RunCreation\DataTransfer\TimeSpanValue.cs" />
     <Compile Include="RunCreation\DataTransfer\PercentValue.cs" />
@@ -295,4 +297,5 @@
     <Compile Include="RunCreation\DataTransfer\StringValue.cs" />
     <Compile Include="RunCreation\DataTransfer\Value.cs" />
+    <Compile Include="RunCreation\MissingSolution.cs" />
     <Compile Include="RunCreation\MissingProblem.cs" />
     <Compile Include="RunCreation\RunCreationService.cs" />
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/Convert.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/Convert.cs	(revision 15081)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/Convert.cs	(revision 15082)
@@ -38,4 +38,15 @@
       if (source == null) return null;
       return new DT.Problem { Id = source.Id, Name = source.Name, Description = source.Description, ProblemClass = Convert.ToDto(source.ProblemClass), DataType = Convert.ToDto(source.DataType) };
+    }
+
+    public static DT.SingleObjectiveSolution ToDto(DA.SingleObjectiveSolution source) {
+      if (source == null) return null;
+      return new DT.SingleObjectiveSolution() {
+        Id = source.Id,
+        ProblemId = source.ProblemId.Value,
+        RunId = source.RunId,
+        Quality = source.Quality,
+        DataType = ToDto(source.DataType)
+      };
     }
 
@@ -165,7 +176,7 @@
     }
 
-    private static DA.DataType ToEntity(DT.DataType source, DA.OKBDataContext okb) {
-      if (source == null) return null;
-      var entity = okb.DataTypes.Where(x => (x.Name == source.Name) && (x.TypeName == source.TypeName)).FirstOrDefault();
+    public static DA.DataType ToEntity(DT.DataType source, DA.OKBDataContext okb) {
+      if (source == null) return null;
+      var entity = okb.DataTypes.FirstOrDefault(x => (x.Name == source.Name) && (x.TypeName == source.TypeName));
       if (entity == null)
         entity = new DA.DataType() { Id = 0, Name = source.Name, TypeName = source.TypeName };
@@ -175,5 +186,5 @@
     private static DA.ValueName ToEntity(string name, DA.ValueNameCategory category, DA.ValueNameType type, DA.OKBDataContext okb) {
       if (string.IsNullOrEmpty(name)) return null;
-      var entity = okb.ValueNames.Where(x => (x.Name == name) && (x.Category == category) && (x.Type == type)).FirstOrDefault();
+      var entity = okb.ValueNames.FirstOrDefault(x => (x.Name == name) && (x.Category == category) && (x.Type == type));
       if (entity == null)
         entity = new DA.ValueName() { Id = 0, Name = name, Category = category, Type = type };
@@ -188,9 +199,9 @@
       }
 
-      var cachedBinaryData = binCache.Where(x => x.Hash.SequenceEqual(hash)).FirstOrDefault();
+      var cachedBinaryData = binCache.FirstOrDefault(x => x.Hash.SequenceEqual(hash));
       if (cachedBinaryData != null)
         return cachedBinaryData;
 
-      var entity = okb.BinaryDatas.Where(x => x.Hash.Equals(hash)).FirstOrDefault();
+      var entity = okb.BinaryDatas.FirstOrDefault(x => x.Hash.Equals(hash));
       if (entity == null) {
         entity = new DA.BinaryData() { Id = 0, Data = data, Hash = hash };
@@ -200,4 +211,26 @@
       return entity;
     }
+
+    public static DA.SingleObjectiveSolution ToEntity(DT.SingleObjectiveSolution source, byte[] data, DA.OKBDataContext okb) {
+      var sol = okb.SingleObjectiveSolutions.SingleOrDefault(x => x.Id == source.Id) ?? new DA.SingleObjectiveSolution() {
+        ProblemId = source.ProblemId,
+        RunId = source.RunId,
+        Quality = source.Quality
+      };
+      if (source.DataType != null) {
+        sol.DataType = ToEntity(source.DataType, okb);
+      }
+      if (data != null && data.Length > 0) {
+        byte[] hash;
+        using (var sha1 = SHA1.Create()) {
+          hash = sha1.ComputeHash(data);
+        }
+        sol.BinaryData = new DA.BinaryData() {
+          Data = data,
+          Hash = hash
+        };
+      }
+      return sol;
+    }
     #endregion
   }
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/DataTransfer/SingleObjectiveSolution.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/DataTransfer/SingleObjectiveSolution.cs	(revision 15082)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/DataTransfer/SingleObjectiveSolution.cs	(revision 15082)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.Services.OKB.RunCreation.DataTransfer {
+  [DataContract]
+  public class SingleObjectiveSolution : Solution {
+    [DataMember]
+    public double Quality { get; set; }
+  }
+}
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/DataTransfer/Solution.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/DataTransfer/Solution.cs	(revision 15082)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/DataTransfer/Solution.cs	(revision 15082)
@@ -0,0 +1,37 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Runtime.Serialization;
+
+namespace HeuristicLab.Services.OKB.RunCreation.DataTransfer {
+  [DataContract]
+  [KnownType(typeof(SingleObjectiveSolution))]
+  public class Solution {
+    [DataMember]
+    public long Id { get; set; }
+    [DataMember]
+    public long ProblemId { get; set; }
+    [DataMember]
+    public long? RunId { get; set; }
+    [DataMember]
+    public DataType DataType { get; set; }
+  }
+}
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/IRunCreationService.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/IRunCreationService.cs	(revision 15081)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/IRunCreationService.cs	(revision 15082)
@@ -20,8 +20,8 @@
 #endregion
 
+using HeuristicLab.Services.OKB.RunCreation.DataTransfer;
 using System.Collections.Generic;
 using System.Net.Security;
 using System.ServiceModel;
-using HeuristicLab.Services.OKB.RunCreation.DataTransfer;
 
 namespace HeuristicLab.Services.OKB.RunCreation {
@@ -44,4 +44,21 @@
 
     [OperationContract]
+    [FaultContract(typeof(MissingProblem))]
+    IEnumerable<Solution> GetSolutions(long problemId);
+
+    [OperationContract]
+    Solution GetSolution(long solutionId);
+
+    [OperationContract]
+    [FaultContract(typeof(MissingSolution))]
+    byte[] GetSolutionData(long solutionId);
+
+    [OperationContract]
+    long AddSolution(Solution solution, byte[] data);
+
+    [OperationContract]
+    void DeleteSolution(Solution solution);
+
+    [OperationContract]
     void AddRun(Run run);
 
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/MissingProblem.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/MissingProblem.cs	(revision 15081)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/MissingProblem.cs	(revision 15082)
@@ -28,6 +28,6 @@
     public string Message { get; set; }
 
-    public MissingProblem(string message, params object[] c) {
-      Message = string.Format(message, c);
+    public MissingProblem(long problemId) {
+      Message = string.Format("Problem with id {0} cannot be found", problemId);
     }
   }
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/MissingSolution.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/MissingSolution.cs	(revision 15082)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/MissingSolution.cs	(revision 15082)
@@ -0,0 +1,34 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2016 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Runtime.Serialization;
+
+namespace HeuristicLab.Services.OKB.RunCreation {
+  [DataContract]
+  public class MissingSolution {
+    [DataMember]
+    public string Message { get; set; }
+
+    public MissingSolution(long solutionId) {
+      Message = string.Format("Solution with id {0} cannot be found", solutionId);
+    }
+  }
+}
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/RunCreationService.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/RunCreationService.cs	(revision 15081)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/RunCreationService.cs	(revision 15082)
@@ -20,4 +20,6 @@
 #endregion
 
+using HeuristicLab.Services.Access;
+using HeuristicLab.Services.OKB.DataAccess;
 using System;
 using System.Collections.Generic;
@@ -25,6 +27,4 @@
 using System.Linq;
 using System.ServiceModel;
-using HeuristicLab.Services.Access;
-using HeuristicLab.Services.OKB.DataAccess;
 
 namespace HeuristicLab.Services.OKB.RunCreation {
@@ -127,4 +127,92 @@
     }
 
+    public IEnumerable<DataTransfer.Solution> GetSolutions(long problemId) {
+      roleVerifier.AuthenticateForAnyRole(OKBRoles.OKBAdministrator, OKBRoles.OKBUser);
+
+      using (OKBDataContext okb = new OKBDataContext()) {
+        var problem = okb.Problems.SingleOrDefault(x => x.Id == problemId);
+        if (problem == null) throw new FaultException<MissingProblem>(new MissingProblem(problemId));
+        // TODO: In case of multi-objective problems one has to check whether it contains single- or multi-objective problems
+        var result = problem.SingleObjectiveSolutions.Select(x => Convert.ToDto(x)).ToList();
+        if (roleVerifier.IsInRole(OKBRoles.OKBAdministrator)) {
+          return result;
+        } else {
+          var problemUsers = okb.ProblemUsers.Where(x => x.ProblemId == problemId).ToList();
+          if (problemUsers.Count == 0 || userManager.VerifyUser(userManager.CurrentUserId, problemUsers.Select(y => y.UserGroupId).ToList())) {
+            return result;
+          } else {
+            return null;
+          }
+        }
+      }
+    }
+
+    public DataTransfer.Solution GetSolution(long solutionId) {
+      roleVerifier.AuthenticateForAnyRole(OKBRoles.OKBAdministrator, OKBRoles.OKBUser);
+
+      using (OKBDataContext okb = new OKBDataContext()) {
+        // TODO: In case of multi-objective problems one has to check whether it contains single- or multi-objective problems
+        var result = Convert.ToDto(okb.SingleObjectiveSolutions.SingleOrDefault(x => x.Id == solutionId));
+        if (roleVerifier.IsInRole(OKBRoles.OKBAdministrator)) {
+          return result;
+        } else {
+          var problemUsers = okb.ProblemUsers.Where(x => x.ProblemId == result.ProblemId).ToList();
+          if (problemUsers.Count == 0 || userManager.VerifyUser(userManager.CurrentUserId, problemUsers.Select(y => y.UserGroupId).ToList())) {
+            return result;
+          } else {
+            return null;
+          }
+        }
+      }
+    }
+
+    public byte[] GetSolutionData(long solutionId) {
+      roleVerifier.AuthenticateForAnyRole(OKBRoles.OKBAdministrator, OKBRoles.OKBUser);
+
+      using (OKBDataContext okb = new OKBDataContext()) {
+        var solution = okb.SingleObjectiveSolutions.SingleOrDefault(x => x.Id == solutionId);
+        if (solution == null) throw new FaultException<MissingSolution>(new MissingSolution(solutionId));
+
+        var result = solution.BinaryData.Data.ToArray();
+        if (roleVerifier.IsInRole(OKBRoles.OKBAdministrator)) {
+          return result;
+        } else {
+          var problemUsers = okb.ProblemUsers.Where(x => x.ProblemId == solution.ProblemId).ToList();
+          if (problemUsers.Count == 0 || userManager.VerifyUser(userManager.CurrentUserId, problemUsers.Select(y => y.UserGroupId).ToList())) {
+            return result;
+          } else {
+            return null;
+          }
+        }
+      }
+    }
+
+    public long AddSolution(DataTransfer.Solution solution, byte[] data) {
+      roleVerifier.AuthenticateForAnyRole(OKBRoles.OKBAdministrator, OKBRoles.OKBUser);
+
+      using (OKBDataContext okb = new OKBDataContext()) {
+        var soSolution = solution as DataTransfer.SingleObjectiveSolution;
+        if (soSolution != null) {
+          DataAccess.SingleObjectiveSolution entity = Convert.ToEntity(soSolution, data, okb);
+          okb.SingleObjectiveSolutions.InsertOnSubmit(entity);
+          okb.SubmitChanges();
+          return entity.Id;
+        }
+      }
+      throw new FaultException(new FaultReason("The solution could not be added."));
+    }
+
+    public void DeleteSolution(DataTransfer.Solution solution) {
+      roleVerifier.AuthenticateForAnyRole(OKBRoles.OKBAdministrator, OKBRoles.OKBUser);
+
+      using (OKBDataContext okb = new OKBDataContext()) {
+        var soSolution = solution as DataTransfer.SingleObjectiveSolution;
+        if (soSolution != null) {
+          okb.SingleObjectiveSolutions.DeleteOnSubmit(okb.SingleObjectiveSolutions.Single(x => x.Id == soSolution.Id));
+          okb.SubmitChanges();
+        }
+      }
+    }
+
     public void AddRun(DataTransfer.Run run) {
       roleVerifier.AuthenticateForAnyRole(OKBRoles.OKBAdministrator, OKBRoles.OKBUser);
@@ -150,5 +238,5 @@
       using (OKBDataContext okb = new OKBDataContext()) {
         var problem = okb.Problems.SingleOrDefault(x => x.Id == problemId);
-        if (problem == null) throw new FaultException<MissingProblem>(new MissingProblem("Problem with id {0} cannot be found", problemId));
+        if (problem == null) throw new FaultException<MissingProblem>(new MissingProblem(problemId));
 
         DoSetCharacteristicValue(okb, problem, value);
@@ -162,5 +250,5 @@
       using (OKBDataContext okb = new OKBDataContext()) {
         var problem = okb.Problems.SingleOrDefault(x => x.Id == problemId);
-        if (problem == null) throw new FaultException<MissingProblem>(new MissingProblem("Problem with id {0} cannot be found", problemId));
+        if (problem == null) throw new FaultException<MissingProblem>(new MissingProblem(problemId));
 
         foreach (var v in values) {
