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 14190)
+++ stable/HeuristicLab.Services.OKB/3.3/HeuristicLab.Services.OKB-3.3.csproj	(revision 15081)
@@ -295,6 +295,8 @@
     <Compile Include="RunCreation\DataTransfer\StringValue.cs" />
     <Compile Include="RunCreation\DataTransfer\Value.cs" />
+    <Compile Include="RunCreation\MissingProblem.cs" />
     <Compile Include="RunCreation\RunCreationService.cs" />
     <Compile Include="RunCreation\IRunCreationService.cs" />
+    <Compile Include="RunCreation\UnknownCharacteristicType.cs" />
   </ItemGroup>
   <ItemGroup>
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/Convert.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/Convert.cs	(revision 14190)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/Convert.cs	(revision 15081)
@@ -68,4 +68,61 @@
         entity.Values.Add(Convert.ToEntity(value, entity, DA.ValueNameCategory.Result, okb, binCache));
       return entity;
+    }
+
+    public static DT.Value ToDto(DA.CharacteristicValue source) {
+      if (source == null) return null;
+      if (source.Characteristic.Type == DA.CharacteristicType.Bool) {
+        return new DT.BoolValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.BoolValue.GetValueOrDefault() };
+      } else if (source.Characteristic.Type == DA.CharacteristicType.Int) {
+        return new DT.IntValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.IntValue.GetValueOrDefault() };
+      } else if (source.Characteristic.Type == DA.CharacteristicType.TimeSpan) {
+        return new DT.TimeSpanValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.LongValue.GetValueOrDefault() };
+      } else if (source.Characteristic.Type == DA.CharacteristicType.Long) {
+        return new DT.LongValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.LongValue.GetValueOrDefault() };
+      } else if (source.Characteristic.Type == DA.CharacteristicType.Float) {
+        return new DT.FloatValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.FloatValue.GetValueOrDefault() };
+      } else if (source.Characteristic.Type == DA.CharacteristicType.Double) {
+        return new DT.DoubleValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.DoubleValue.GetValueOrDefault() };
+      } else if (source.Characteristic.Type == DA.CharacteristicType.Percent) {
+        return new DT.PercentValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.DoubleValue.GetValueOrDefault() };
+      } else if (source.Characteristic.Type == DA.CharacteristicType.String) {
+        return new DT.StringValue { Name = source.Characteristic.Name, DataType = Convert.ToDto(source.DataType), Value = source.StringValue };
+      } else {
+        throw new ArgumentException("Unknown characteristic type.", "source");
+      }
+    }
+
+    public static DA.CharacteristicValue ToEntity(DT.Value source, DA.OKBDataContext okb, DA.Problem problem, DA.CharacteristicType type) {
+      if (okb == null || problem == null || source == null || string.IsNullOrEmpty(source.Name)) throw new ArgumentNullException();
+      var entity = new DA.CharacteristicValue();
+      entity.Problem = problem;
+      entity.DataType = Convert.ToEntity(source.DataType, okb);
+      entity.Characteristic = Convert.ToEntity(source.Name, type, okb);
+      if (source is DT.BoolValue) {
+        entity.BoolValue = ((DT.BoolValue)source).Value;
+      } else if (source is DT.IntValue) {
+        entity.IntValue = ((DT.IntValue)source).Value;
+      } else if (source is DT.TimeSpanValue) {
+        entity.LongValue = ((DT.TimeSpanValue)source).Value;
+      } else if (source is DT.LongValue) {
+        entity.LongValue = ((DT.LongValue)source).Value;
+      } else if (source is DT.FloatValue) {
+        entity.FloatValue = ((DT.FloatValue)source).Value;
+      } else if (source is DT.DoubleValue) {
+        entity.DoubleValue = ((DT.DoubleValue)source).Value;
+      } else if (source is DT.PercentValue) {
+        entity.DoubleValue = ((DT.PercentValue)source).Value;
+      } else if (source is DT.StringValue) {
+        entity.StringValue = ((DT.StringValue)source).Value;
+      } else {
+        throw new ArgumentException("Unknown characteristic type.", "source");
+      }
+      return entity;
+    }
+
+    private static DA.Characteristic ToEntity(string name, DA.CharacteristicType type, DA.OKBDataContext okb) {
+      if (string.IsNullOrEmpty(name)) return null;
+      var entity = okb.Characteristics.FirstOrDefault(x => (x.Name == name) && (x.Type == type));
+      return entity ?? new DA.Characteristic() { Id = 0, Name = name, Type = type };
     }
 
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/IRunCreationService.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/IRunCreationService.cs	(revision 14190)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/IRunCreationService.cs	(revision 15081)
@@ -45,4 +45,17 @@
     [OperationContract]
     void AddRun(Run run);
+
+    [OperationContract]
+    IEnumerable<Value> GetCharacteristicValues(long problemId);
+
+    [OperationContract]
+    [FaultContract(typeof(MissingProblem))]
+    [FaultContract(typeof(UnknownCharacteristicType))]
+    void SetCharacteristicValue(long problemId, Value value);
+
+    [OperationContract]
+    [FaultContract(typeof(MissingProblem))]
+    [FaultContract(typeof(UnknownCharacteristicType))]
+    void SetCharacteristicValues(long problemId, Value[] values);
   }
 }
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 15081)
@@ -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 MissingProblem {
+    [DataMember]
+    public string Message { get; set; }
+
+    public MissingProblem(string message, params object[] c) {
+      Message = string.Format(message, c);
+    }
+  }
+}
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/RunCreationService.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/RunCreationService.cs	(revision 14190)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/RunCreationService.cs	(revision 15081)
@@ -20,4 +20,5 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Data.Linq;
@@ -135,4 +136,89 @@
       }
     }
+
+    public IEnumerable<DataTransfer.Value> GetCharacteristicValues(long problemId) {
+      using (OKBDataContext okb = new OKBDataContext()) {
+        var prob = okb.Problems.SingleOrDefault(x => x.Id == problemId);
+        if (prob == null) return Enumerable.Empty<DataTransfer.Value>();
+        return prob.CharacteristicValues.Select(Convert.ToDto).ToArray();
+      }
+    }
+
+    public void SetCharacteristicValue(long problemId, DataTransfer.Value value) {
+      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("Problem with id {0} cannot be found", problemId));
+
+        DoSetCharacteristicValue(okb, problem, value);
+        okb.SubmitChanges();
+      }
+    }
+
+    public void SetCharacteristicValues(long problemId, DataTransfer.Value[] values) {
+      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("Problem with id {0} cannot be found", problemId));
+
+        foreach (var v in values) {
+          DoSetCharacteristicValue(okb, problem, v);
+        }
+        okb.SubmitChanges();
+      }
+    }
+
+    private void DoSetCharacteristicValue(OKBDataContext okb, Problem problem, DataTransfer.Value value) {
+      CharacteristicType characteristicType;
+      try {
+        characteristicType = GetCharacteristicType(value);
+      } catch (ArgumentException ex) {
+        throw new FaultException<UnknownCharacteristicType>(new UnknownCharacteristicType(ex.Message));
+      }
+
+      var entity = problem.CharacteristicValues.SingleOrDefault(x => x.Characteristic.Name == value.Name && x.Characteristic.Type == characteristicType);
+      if (entity != null) {
+        // Update
+        switch (characteristicType) {
+          case CharacteristicType.Bool: entity.BoolValue = ((DataTransfer.BoolValue)value).Value; break;
+          case CharacteristicType.Int: entity.IntValue = ((DataTransfer.IntValue)value).Value; break;
+          case CharacteristicType.Long: entity.LongValue = ((DataTransfer.LongValue)value).Value; break;
+          case CharacteristicType.Float: entity.FloatValue = ((DataTransfer.FloatValue)value).Value; break;
+          case CharacteristicType.Double: entity.DoubleValue = ((DataTransfer.DoubleValue)value).Value; break;
+          case CharacteristicType.Percent: entity.DoubleValue = ((DataTransfer.PercentValue)value).Value; break;
+          case CharacteristicType.String: entity.StringValue = ((DataTransfer.StringValue)value).Value; break;
+          case CharacteristicType.TimeSpan: entity.LongValue = ((DataTransfer.TimeSpanValue)value).Value; break;
+        }
+      } else {
+        // Insert
+        entity = Convert.ToEntity(value, okb, problem, characteristicType);
+        okb.CharacteristicValues.InsertOnSubmit(entity);
+      }
+
+    }
+
+    private CharacteristicType GetCharacteristicType(DataTransfer.Value source) {
+      if (source is DataTransfer.BoolValue) {
+        return CharacteristicType.Bool;
+      } else if (source is DataTransfer.IntValue) {
+        return CharacteristicType.Int;
+      } else if (source is DataTransfer.TimeSpanValue) {
+        return CharacteristicType.TimeSpan;
+      } else if (source is DataTransfer.LongValue) {
+        return CharacteristicType.Long;
+      } else if (source is DataTransfer.FloatValue) {
+        return CharacteristicType.Float;
+      } else if (source is DataTransfer.DoubleValue) {
+        return CharacteristicType.Double;
+      } else if (source is DataTransfer.PercentValue) {
+        return CharacteristicType.Percent;
+      } else if (source is DataTransfer.StringValue) {
+        return CharacteristicType.String;
+      } else {
+        throw new ArgumentException("Unknown characteristic type.", "source");
+      }
+    }
   }
 }
Index: stable/HeuristicLab.Services.OKB/3.3/RunCreation/UnknownCharacteristicType.cs
===================================================================
--- stable/HeuristicLab.Services.OKB/3.3/RunCreation/UnknownCharacteristicType.cs	(revision 15081)
+++ stable/HeuristicLab.Services.OKB/3.3/RunCreation/UnknownCharacteristicType.cs	(revision 15081)
@@ -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 UnknownCharacteristicType {
+    [DataMember]
+    public string Message { get; set; }
+
+    public UnknownCharacteristicType(string message, params object[] c) {
+      Message = string.Format(message, c);
+    }
+  }
+}
