Home > Mobile >  How would I go about saving an EFCore DBSet as JSON?
How would I go about saving an EFCore DBSet as JSON?

Time:08-24

Hoping to get pointed in the right direction regarding some confusion with Entity Framework Core, .NET 5 if it matters.

The context for this question is an "E2E" test for lack of a better term, which is fed a scenario. (ScenarioForm, posted below) The requirement is to have a database table which tracks a given scenario and the status of it's execution, along with some unimportant metrics for the sake of this question.

This form is fed from a service/controller and is a JSON object. This is currently JSON because we're early days with what our "scenario" is, and want to be able to change it fairly easily. I got this requirement from someone higher up so please consider this requirement a constant.

using System;
using Microsoft.EntityFrameworkCore;
using MyNamespace.Contracts.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace MyNamespace.Contracts.Forms
{
    /// <summary>
    /// Defines the execution parameters of a scenario.
    /// </summary>
    [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
    [Keyless] // This is me trying to figure things out, probably no need to include keyless..?
    public class ScenarioForm
    {
        /// <summary>
        /// Quantity of customers created by this scenario.
        /// </summary>
        public int CustomerCount { get; set; } = 1;

        /// <summary>
        /// Id of the Organization to use in this scenario
        /// </summary>
        public Guid OrganizationId { get; set; }

        /// <summary>
        /// Type of running, whether it be from a stream or file.
        /// </summary>
        public RunnerType RunnerType { get; set; } = RunnerType.File;
    }
}

I also have an entity, which is supposed to be the representation of the status of a given scenario.

using System;
using System.ComponentModel.DataAnnotations.Schema;
using MyNamespace.Contracts.Forms;
using MyNamespace.Contracts.Models;

namespace MyNamespace.Data.Entities
{
    public class ScenarioStatus
    {
        public Guid Id { get; set; }
        [NotMapped] // This is leftover from me trying stuff, I imagine this should be a different relationship.
        public ScenarioForm Specification { get; set; }
        public RunnerType RunnerType { get; set; }
        public DateTime? StartedAt { get; set; }
        public DateTime? CompletedAt { get; set; }
        public DateTime? ElapsedTime { get; set; }
        public string CreatedBy { get; set; }
        public DateTime CreatedAt { get; set; }
        public string UpdatedBy { get; set; }
        public DateTime? UpdatedAt { get; set; }
    }
}

The issue that I'm running into is that I would like the ScenarioForm to just be a column in the ScenarioStatus table, as its JSON representation, instead of having an entirely seperate table for the ScenarioForm.

I'm also aware that it's not ideal to be defining these relationships via attributes, feel free to give direction as either attributes or using FluentAPI.

Any direction appreciated please and thanks!

I chopped the code up a little bit, so if there is anything confusing let me know and I can clarify.

CodePudding user response:

There is two way based on which database you are using.

  1. if you use Postgres easily, you can use jsonb type, and it's saved as JSON in the database. For more information read this
    public class ScenarioStatus
    {
        public Guid Id { get; set; }
        [Column(TypeName = "jsonb")]
        public ScenarioForm Specification { get; set; }
        public RunnerType RunnerType { get; set; }
        public DateTime? StartedAt { get; set; }
        public DateTime? CompletedAt { get; set; }
        public DateTime? ElapsedTime { get; set; }
        public string CreatedBy { get; set; }
        public DateTime CreatedAt { get; set; }
        public string UpdatedBy { get; set; }
        public DateTime? UpdatedAt { get; set; }
    }
  1. use a converter to convert a property into JSON
public class ScenarioStatusConfiguration : IEntityTypeConfiguration<ScenarioStatus>
{
    public void Configure(EntityTypeBuilder<ScenarioStatus> builder)
    {
        builder.Property(e => e.Specification).HasConversion(
            v => JsonConvert.SerializeObject(v),
            v => JsonConvert.DeserializeObject<Specification>(v)
        );
    }
}
  • Related