Skip to content

Instantly share code, notes, and snippets.

@johnknoop
Created March 15, 2022 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnknoop/6868d069b6ff23486614f8195d936f44 to your computer and use it in GitHub Desktop.
Save johnknoop/6868d069b6ff23486614f8195d936f44 to your computer and use it in GitHub Desktop.
Polymorphic model
namespace DeviceService.Api.Contracts;
public record DeviceMetadata(Guid MetadataFieldId, System.Text.Json.JsonElement Value);
public record DeviceToCreate(Guid DeviceTypeId, string DeviceName, IList<DeviceMetadata> MetaData);
public record BulkCreateDevicesRequest(IList<DeviceToCreate> Devices);
/*
Example:
{
"devices": [
{
"deviceTypeId": "23423f-4g65465-ase4ts5vg-56ey56e",
"name": "Kullen 1",
"metadata": [
{
"metadataFieldId": "23423f-4g65465-ase4ts5vg-56ey56e",
"value": 23.543
},
{
"metadataFieldId": "23423f-4g65465-ase4ts5vg-56ey56e",
"value": "2022-01-01"
},
{
"metadataFieldId": "23423f-4g65465-ase4ts5vg-56ey56e",
"value": false
}
]
}
]
}
*/
IDictionary<Guid, Domain.Metadata.MetadataFieldBase> LoadMetadataFieldsFromDatabase(ICollection<Guid> metadataFieldIds)
{
// Here we wanna do dbContext.MetadataFields.Where(x => metadataFieldIds.Contains(x.Id))
}
IDictionary<Guid, DeviceType> LoadDeviceTypesFromDatabase(ICollection<Guid> deviceTypeIds)
{
// Here we wanna do dbContext.DeviceTypes.Where(x => deviceTypeIds.Contains(x.Id))
}
[HttpPost("bulk/create")]
public async Task BulkCreateDevices(BulkCreateDevicesRequest request)
{
// Load all the referenced metadatafields upfront for performance reasons:
var metadataFieldsReferenced = LoadMetadataFieldsFromDatabase(request.Devices.SelectMany(x => x.MetaData.Select(y => y.MetadataFieldId)).ToList());
// Load all the referenced device types upfront for performance reasons:
var allReferencedDeviceTypes = LoadDeviceTypesFromDatabase(request.Devices.Select(x => x.DeviceTypeId).ToList());
var devicesToInsert = request.Devices.Select(d =>
new Device(
name: d.DeviceName,
deviceType: allReferencedDeviceTypes[d.DeviceTypeId],
metadata: d.MetaData.Select<DeviceMetadata, MetadataFieldValueBase>(m => {
return metadataFieldsReferenced.TryGetValue(m.MetadataFieldId, out var referencedField)
? referencedField switch {
StringMetadataField field => field.CreateValue(new Guid(), m.Value.GetString()),
IntMetadataField field => field.CreateValue(new Guid(), m.Value.GetInt32()),
_ => throw new NotImplementedException("todo: cover all the types")
}
: throw new Exception("");
}).ToList()
)
);
// await db.Context.InsertAsync(devicesToInsert)
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DeviceService.Domain.Types;
namespace DeviceService.Domain.Metadata;
#region Fields
public abstract class MetadataFieldBase
{
protected MetadataFieldBase(Guid id, string name)
{
Id = id;
Name = name;
}
public Guid Id { get; private set; }
public string Name { get; private set; }
}
public class StringMetadataField : MetadataFieldBase
{
public StringMetadataField(Guid id, string name) : base(id, name) { }
public StringMetadataValue CreateValue(Guid id, string value)
{
return new StringMetadataValue(id, value);
}
}
public class IntMetadataField : MetadataFieldBase
{
public IntMetadataField(string unitOfMeasure, Guid id, string name) : base(id, name)
{
UnitOfMeasure = unitOfMeasure;
}
public string UnitOfMeasure { get; private set; }
public int MinValue { get; private set; }
public IntMetadataValue CreateValue(Guid id, int value)
{
if (value < MinValue) {
throw new Exception("Ajabaja");
}
return new IntMetadataValue(id, value);
}
}
public class DateMetadataField : MetadataFieldBase
{
public DateMetadataField(Guid id, string name) : base(id, name) { }
}
#endregion
#region Values
public abstract class MetadataFieldValueBase
{
protected MetadataFieldValueBase(Guid id)
{
Id = id;
}
public Guid Id { get; private set; }
}
public class StringMetadataValue : MetadataFieldValueBase
{
internal StringMetadataValue(Guid id, string value) : base(id)
{
Value = value;
}
public string Value { get; private set; }
}
public class IntMetadataValue : MetadataFieldValueBase
{
internal IntMetadataValue(Guid id, int value) : base(id)
{
Value = value;
}
public int Value { get; private set; }
}
public class DateMetadataValue : MetadataFieldValueBase
{
internal DateMetadataValue(Guid id, DateTime value) : base(id)
{
Value = value;
}
public DateTime Value { get; private set; }
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment