Time Series Providers – Guide & Recipes¶
A compact, developer-friendly map of all Time Series providers and how to wire and use them with the same service surface.
See also (deep dives)¶
Pick the right provider¶
| Provider | Read/Write | Grouped | IDs you pass | Best for | Notes |
|---|---|---|---|---|---|
MCLite – DB (Provider.MCLite.TimeSeriesRepository) |
R/W | ✓ | /group/sub/Name |
Operational stores in MC/Lite (PG/SQL/SQLite) | Raw/Blob storage, flags, aggregation (incl. ensembles), window deletes |
MCLite – from Spreadsheet (Provider.MCLite.TimeSeriesFromSpreadsheetRepository) |
Read-only | — | Spreadsheet=/calc/Book.xlsx;Timeseries=/out/Name[;TrimBlanks=true] |
Compositions & quick calcs in Excel | Fills Data sheet, recalculates, reads Output named series |
MIKECore – dfs0 (grouped) (Provider.MIKECore.Dfs0GroupedTimeSeriesRepository) |
R/W | ✓ | path\file.dfs0;ItemName |
Many .dfs0 under a root |
Update rewrites multi-item files; Remove deletes file when last item |
MIKECore – dfs0 (single file) (Provider.MIKECore.Dfs0TimeSeriesRepository) |
R/W | — | 3(name:WL)[eum:eumIWaterLevel] or WaterLevel |
One .dfs0 at a time |
SetValues only when file has one item |
| MIKECore – dfs2 / dfsu | Read-only | — | key=value;... (XY / LatLon / Polygon / ElementId) |
Extract point/area series from gridded files | dfs2 supports True-North reprojection; dfsu supports 3D LayerNumber |
MIKECloud (Provider.MIKECloud.GroupedTimeSeriesRepository) |
R/W | ✓ | /Sub1/Sub2/Dataset/SeriesName |
Cloud datasets | Creates subprojects; dataset must exist; update is delete+recreate |
MIKE1D results (Provider.MIKE1D.ResultFileGroupedTimeSeriesRepository) |
Read-only | ✓ | Group/Run/File.res1d/Type;Quantity;Id[;chainage] |
.res1d/.res11 runs |
Node/Reach/Catchment; shared time axis |
USGS DV (Provider.USGS.TimeSeriesRepository) |
Read-only | — | USGS:Site:Param:Stat |
Observed daily values | Returns qualifiers as flags; EUM metadata mapped |
All providers plug into
DHI.Services.TimeSeriesservices, so your calling code stays the same.
Wire it in ~90 seconds¶
MCLite (database-backed)¶
using DHI.Services.TimeSeries;
using DHI.Services.Provider.MCLite;
var repo = new TimeSeriesRepository("database=mc2014.2"); // PG/SQL/SQLite via keys
var svc = new TimeSeriesService<string,double>(repo); // grouped & updatable
ServiceLocator.Register(svc, "mc-ts"); // {connectionId}
MIKECore dfs0 (grouped)¶
using DHI.Services.Provider.MIKECore;
var repo = new Dfs0GroupedTimeSeriesRepository(@"C:\data"); // root with .dfs0 files
ServiceLocator.Register(new TimeSeriesService<string,double>(repo), "dfs0-grouped");
MIKECloud¶
using DHI.Services.Provider.MIKECloud;
var repo = new GroupedTimeSeriesRepository("apiKey=...;projectId=...;environment=Prod");
ServiceLocator.Register(new GroupedUpdatableTimeSeriesService<string,double>(repo), "mc-cloud");
Prefer the Connections module in hosts; see JSON examples in §7.
IDs & groups — cheat sheet¶
- FullName:
"/group/sub/Name"(no trailing slash for series). - Group tree modifiers (suffix on group string):
;nonrecursive·;groupsonly·;nonrecursive;groupsonly
Provider-specific IDs
- MCLite DB:
/Hydro/Basin/Stage - MCLite from Spreadsheet:
Spreadsheet=/calc/Book.xlsx;Timeseries=/out/Stage;TrimBlanks=true - dfs0 (grouped):
data\stations\a.dfs0;WaterLevel - dfs0 (single file):
3(name:WaterLevel)[eum:eumIWaterLevel]orWaterLevel - dfs2:
Item=HS;Latitude=55.0;Longitude=12.0orItem=HS;PolygonLngLat=lon,lat,...;AreaStatistic=Average - dfsu:
Item=Salinity;X=700000;Y=6175000[;LayerNumber=3] - MIKECloud:
/Ops/North/Telemetry/WaterLevel(dataset is the group; last segment is name) - USGS:
USGS:11458000:00060:00003
Common tasks (works the same across R/W providers)¶
var id = "/import/Well7/Head";
// Create if missing
if (!svc.Contains(id)) {
var ts = new TimeSeries<string,double>(id, "Head", "/import/Well7") {
Quantity = "WaterLevel", Unit = "m", DataType = TimeSeriesDataType.Instantaneous
};
svc.Add(ts);
}
// Write (dedup per second by default on MCLite DB)
var data = new TimeSeriesData<double>();
data.Append(DateTime.UtcNow.AddHours(-1), 1.23);
data.Append(DateTime.UtcNow, 1.31);
svc.SetValues(id, data);
// Read window
var window = svc.GetValues(id, DateTime.UtcNow.AddDays(-7), DateTime.UtcNow).Value;
// Aggregate
var avg7d = svc.GetAggregatedValue(id, AggregationType.Average,
DateTime.UtcNow.AddDays(-7), DateTime.UtcNow).Value;
Flags (MCLite DB, MIKECloud returns null flags):
var flagged = new TimeSeriesDataWFlag<double,int?>();
flagged.Append(t0, 1.23, 101);
flagged.Append(t1, null, null);
svc.SetValues(id, flagged); // preserves duplicates exactly (no dedup pass)
Provider-specific quick recipes¶
dfs0 (grouped): replace an item inside a multi-item file¶
var id = @"data\stations\a.dfs0;WaterLevel";
var entity = repo.Get(id).Value;
entity.Data = window; // your new values
repo.Update(entity); // rewrites the file
dfs2: True-North reprojection¶
var u = repo.GetValues("Item=U;UItem=U;VItem=V;Latitude=55.676;Longitude=12.568").Value; // True East/West
var d = repo.GetValues("Item=CurrentDirection;Latitude=55.676;Longitude=12.568;ReprojectNorth=true").Value;
MCLite from Spreadsheet: compute series¶
Spreadsheet has Definitions, Data, Output (row 0 names every second col).
var sid = "Spreadsheet=/calc/RatingCurves.xlsx;Timeseries=/computed/FlowAtS2;TrimBlanks=true";
var vals = svc.GetValues(sid, DateTime.Parse("2024-01-01"), DateTime.Parse("2024-02-01")).Value;
MIKECloud: safe replace of a window¶
repo.RemoveValues("/Hydro/Observations/WaterLevel", t0, t1);
repo.SetValues("/Hydro/Observations/WaterLevel", newData);
Web API pairing (Connections JSON samples)¶
{
"$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[DHI.Services.IConnection, DHI.Services]], mscorlib",
"mc-ws1": {
"$type": "DHI.Services.TimeSeries.WebApi.GroupedUpdatableTimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
"ConnectionString": "database=mc2014.2",
"RepositoryType": "DHI.Services.Provider.MCLite.TimeSeriesRepository, DHI.Services.Provider.MCLite",
"Name": "MCLite DB time series",
"Id": "mc-ws1"
},
"dfs0-grouped": {
"$type": "DHI.Services.TimeSeries.WebApi.GroupedDiscreteTimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
"ConnectionString": "[AppData]dfs0",
"RepositoryType": "DHI.Services.Provider.MIKECore.Dfs0GroupedTimeSeriesRepository, DHI.Services.Provider.MIKECore",
"Name": "dfs0 grouped",
"Id": "dfs0-grouped"
},
"dfs2": {
"$type": "DHI.Services.TimeSeries.WebApi.TimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
"ConnectionString": "C:\\Data\\R20141001.dfs2",
"RepositoryType": "DHI.Services.Provider.MIKECore.Dfs2TimeSeriesRepository, DHI.Services.Provider.MIKECore",
"Name": "dfs2",
"Id": "dfs2"
},
"dfsu": {
"$type": "DHI.Services.TimeSeries.WebApi.TimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
"ConnectionString": "C:\\Data\\mesh.dfsu",
"RepositoryType": "DHI.Services.Provider.MIKECore.DfsuTimeSeriesRepository, DHI.Services.Provider.MIKECore",
"Name": "dfsu",
"Id": "dfsu"
},
"mc-cloud": {
"$type": "DHI.Services.TimeSeries.WebApi.GroupedUpdatableTimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
"ConnectionString": "apiKey=[env:MIKECLOUD_APIKEY];projectId=[env:MIKECLOUD_PROJECT];environment=Prod",
"RepositoryType": "DHI.Services.Provider.MIKECloud.GroupedTimeSeriesRepository, DHI.Services.Provider.MIKECloud",
"Name": "MIKECloud time series",
"Id": "mc-cloud"
},
"usgs-dv": {
"$type": "DHI.Services.TimeSeries.WebApi.TimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
"ConnectionString": "https://waterservices.usgs.gov/nwis/dv/?startDT=2024-01-01&endDT=2024-12-31",
"RepositoryType": "DHI.Services.Provider.USGS.TimeSeriesRepository, DHI.Services.Provider.USGS",
"Name": "USGS Daily Values",
"Id": "usgs-dv"
}
}
URL encoding tips
- dfs0 ids with
;must be encoded if you expose the id directly; most APIs use FullName (file/item) in routes. - dfs2/dfsu
key=value;...ids should be URL-encoded as a single token.
Foot-guns & pro tips¶
MCLite DB
- Default dedup is PerSecond. To preserve duplicates, send
ITimeSeriesDataWFlag<double,int?>(even withnullflags). - Raw vs. Blob storage is per series (
storage_type=0|1). Blob writes merge by period (hour/day/week/month/year). RemoveValuesalso purges flags in the window (when flags table exists).- SQL Server floor: times below
SqlDateTime.MinValueare bumped. RemoveByGroupdeletes entities then group tree.
MCLite from Spreadsheet
- Requires sheets
Definitions,Data,Output(row 0 headers every second column). - Each call clears
Dataand recalculates the workbook. Read-only by design. Debug=truewrites a temp snapshot after calc.
MIKECore dfs0
- Single-file repo
SetValuesworks only when the file has a single item. - For multi-item files use grouped repo +
Update. - Equidistant files require equidistant input on
SetValues. RemoveValuesis not implemented.
dfs2/dfsu
- Choose exactly one locator: ElementId or XY or Lat/Lon or Polygon.
- dfs2:
UItem/VItemreprojection returns a True-East/True-North component;ReprojectNorth=truefixes direction items. - dfsu 3D: add
LayerNumber.
MIKECloud
- Provider creates subprojects, not datasets — provision datasets first.
Updatepath is delete+recreate; for values, preferRemoveValues+SetValues.
USGS
- Daily values only. Qualifiers come back as flags; texts live in metadata.
Quick reference¶
| Need… | Use… | Snippet |
|---|---|---|
| Create + write to DB | MCLite DB | svc.Add(ts); svc.SetValues(id, data); |
Replace series inside .dfs0 with other items present |
dfs0 (grouped) | var e = repo.Get(id).Value; e.Data = data; repo.Update(e); |
| Extract point series from grid | dfs2/dfsu | repo.GetValues("Item=HS;Latitude=55.0;Longitude=12.0") |
| Compose series in Excel | MCLite from Spreadsheet | svc.GetValues("Spreadsheet=...;Timeseries=/out/Name") |
| Cloud dataset | MIKECloud | repo.SetValues("/Path/Dataset/Name", data) |
| Observations (DV) | USGS | svc.GetValues("USGS:11458000:00060:00003") |
Bottom line: choose a provider by where your data lives (DB, files, cloud, external), then code once against TimeSeriesService. When in doubt, start with MCLite DB for CRUD + analytics, use dfs0/dfs2/dfsu for MIKE files, MIKECloud for platform datasets, USGS for read-only observations, and Spreadsheet when domain logic lives in Excel.