J'essaie d'extraire des données d'une API externe et de sauvegarder ces données dans une base de données MS SQL à l'aide d'Entity Framework. Je suis nouveau dans Entity Framework et je ne sais pas comment rendre mes données persistantes. La base de données est créée selon le principe Code First selon le modèle suivant:

JsonResponse.cs

public partial class JsonResponse
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    [JsonProperty("prtg-version")]
    public string PrtgVersion { get; set; }
    [JsonProperty("treesize")]
    public int TreeSize { get; set; }
    [JsonProperty("devices")]
    public Devices[] devices { get; set; }
}

public partial class Devices
{
    [Key]
    [JsonProperty("objid")]
    public int objid { get; set; }
    [JsonProperty("probe")]
    public string probe { get; set; }
    [JsonProperty("device")]
    public string device { get; set; }
    [JsonProperty("host")]
    public string host { get; set; }
}

J'ai réussi à recevoir les données de l'API en JSON, à les désérialiser et à les ajouter au List <JsonResponse> dataG. Maintenant, je souhaite rendre ces données persistantes en les enregistrant dans la base de données EF. J'ai du mal à faire cela car mon JsonResponse contient une liste d'objets Devices. Mon contrôleur dans lequel je tire les données de l'API externe se présente comme suit:

CMDBController.cs

public class CMDBController : Controller
{
    private DbContext db = new DbContext();

    public async Task<ActionResult> Test()
    {
        List<JsonResponse> dataG = new List<JsonResponse>();
        using (var httpClient = new HttpClient())
        {
            using (var response = await httpClient
                .GetAsync(
                    "/api/table.json?content=devices&output=json&columns=objid,probe,group,device,host")
            )
            {
                string apiResponse = await response.Content.ReadAsStringAsync();
                var data = JsonConvert.DeserializeObject<JsonResponse>(apiResponse);
                dataG.Add(data);
                var devices = data.devices;

                foreach (var item in devices)
                {
                    db.Add(item);
                    db.SaveChanges();
                }
            }
        }
        return View(dataG);
    }

Les données JSON de l'API ressemblent à ceci:

{
prtg-version: "20.4.63.1412",
treesize: 2,
devices: [
{
objid: 40,
probe: "Local Probe",
group: "Local Probe",
device: "Probe Device",
host: "127.0.0.1"
},
{
objid: 42,
probe: "Local Probe",
group: "Network Infrastructure",
device: "DNS: 84.116.46.23",
host: "84.116.46.23"
}

DBContext

public class FrontDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(
            "Server=(localdb)\\MSSQLLocalDB;Database=FrontDB;MultipleActiveResultSets=true");
    }

    public DbSet<JsonResponse> Responses { get; set; }
}

}

MODIFIER 1

public class CMDBController : Controller
{
    private DbContext db = new DbContext();

    public async Task<ActionResult> Test()
    {
        List<JsonResponse> dataG = new List<JsonResponse>();
        using (var httpClient = new HttpClient())
        {
            using (var response = await httpClient
                .GetAsync(
                    "/api/table.json?content=devices&output=json&columns=objid,probe,group,device,host")
            )
            {
                string apiResponse = await response.Content.ReadAsStringAsync();
                var data = JsonConvert.DeserializeObject<JsonResponse>(apiResponse);
                dataG.Add(data);
                var devices = data.devices;
                db.Responses.AddRange(data);
                db.SaveChanges();
            }
        }
        return View(dataG);
    }
0
Bram 3 nov. 2020 à 05:14

3 réponses

Meilleure réponse

Bonjour c'est ma première réponse et j'apprends l'anglais j'essaierai de faire mieux.

Avez-vous deux tables? Un maître-détail?

Je vous recommande d'organiser votre code et de séparer les responsabilités que vous devez d'abord avoir et Dto Object pour représenter votre objet JSON et une entité pour insérer les données dans une base de données, puis séparer les méthodes, mais je vais vous partager la solution avec votre entité actuelle.

Vous devez d'abord avoir un DbContext avec vos entités et votre chaîne de connexion, un exemple de DbContext avec EntityFrameworkCore:

public class MyDbContext:DbContext
    {
        private readonly string connectionString;

        public MyDbContext(string connectionString)
        {
            this.connectionString = connectionString;
            _migrateDatabase = true;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseMySql(connectionString);
        }

        public DbSet<JsonResponse> JsonResponses { get; set; }
        public DbSet<Devices> Devices { get; set; }
    }

Si vous avez un détail principal, vous devez créer une propriété de navigation avec une clé étrangère dans ce cas, j'ai créé cette propriété dans l'entité Device.

public partial class JsonResponse
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    [JsonProperty("prtg-version")]
    public string PrtgVersion { get; set; }
    [JsonProperty("treesize")]
    public int TreeSize { get; set; }

    [JsonProperty("devices")]
    public List<Devices> devices { get; set; }
}

public partial class Devices
{
    [Key]
    [JsonProperty("objid")]
    public int objid { get; set; }
    [JsonProperty("probe")]
    public string probe { get; set; }
    [JsonProperty("device")]
    public string device { get; set; }
    [JsonProperty("host")]
    public string host { get; set; }

    public int JsonResponseId { get; set; }
    
    [ForeignKey("JsonResponseId")]
    public JsonResponse JsonResponse { get; set; }
}

Pour enregistrer les données, vous devez ajouter l'entité principale et le détail sera enregistré automatiquement:

public class CMDBController : Controller
{
    private MyDbContext db = new MyDbContext("mycnn");

    public async Task<ActionResult> Test()
    {
        JsonResponse data = GetJsonData();
        db.JsonResponses.Add(data);
        db.SaveChanges();
        return View(data);
    }

    JsonResponse GetJsonData(){
         using (var httpClient = new HttpClient())
        {
          var response = await httpClient.GetAsync(
                    "/api/table.json?content=devices&output=json&columns=objid,probe,group,device,host");
          string apiResponse = await response.Content.ReadAsStringAsync();
          return JsonConvert.DeserializeObject<JsonResponse>(apiResponse);
        }
    }
}

Si vous n'avez pas de détail principal et que vous devez enregistrer une plage de données, vous devez utiliser AddRange et enregistrer toutes les données en une seule action:

public async Task<ActionResult> Test()
    {
        JsonResponse data = GetJsonData();
        db.Devices.AddRange(data.Devices);
        db.SaveChanges();
        return View(data);
    }
1
Omar Burgos 3 nov. 2020 à 04:08
Update the DbContextClass


public class MyDbContext:DbContext
{
    private readonly string connectionString;

    public MyDbContext(string connectionString)
    {
        this.connectionString = connectionString;
        _migrateDatabase = true;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseMySql(connectionString);
    }

    public DbSet<JsonResponse> JsonResponses { get; set; }
}

Mettre à jour le contrôleur

public async Task<ActionResult> Test()
{        
    using (var httpClient = new HttpClient())
    {
        using (var response = await httpClient
            .GetAsync(
                "/api/table.json?content=devices&output=json&columns=objid,probe,group,device,host")
        )
        {
            string apiResponse = await response.Content.ReadAsStringAsync();
            var data = JsonConvert.DeserializeObject<JsonResponse>(apiResponse);
            db.JsonResponses.Add(data);
            db.SaveChang();
        }
    }
    return View(dataG);
}
0
mohd afzal 3 nov. 2020 à 06:40

Comme l'a dit marc_s, le cœur d'EF prend en charge l'accès à de nombreuses bases de données différentes, quel type de base de données utilisez-vous?

En règle générale, pour insérer de nouvelles données dans la base de données via EF Core, vous pouvez utiliser la méthode DbContext.Add ou la méthode DbContext.AddRange pour ajouter de nouveaux éléments. Vous pouvez consulter ces articles: EF core Sauvegarde des données.

Je suppose que vous utilisez la base de données du serveur MS SQL, selon votre description, l'objet JsonResponse et Devices contient relation un-à-plusieurs, vous pouvez donc utiliser une propriété de navigation , au lieu d'un Devices[], essayez de modifier votre code comme ci-dessous:

public partial class JsonResponse
{
    [Key] 
    public int Id { get; set; }
    [JsonProperty("prtg-version")]
    public string PrtgVersion { get; set; }
    [JsonProperty("treesize")]
    public int TreeSize { get; set; }
    [JsonProperty("devices")]
    public List<Devices> devices { get; set; }
}

public partial class Devices
{
    [Key()]
    [DatabaseGenerated(DatabaseGeneratedOption.None)] // prevent database auto generate objid.
    [JsonProperty("objid")]
    public int objid { get; set; }
    [JsonProperty("probe")]
    public string probe { get; set; }
    [JsonProperty("device")]
    public string device { get; set; }
    [JsonProperty("host")]
    public string host { get; set; }
}

Ensuite, après la migration et la génération des tables associées dans la base de données, vous pouvez vous référer au code suivant pour insérer de nouveaux éléments dans la base de données:

    private readonly ILogger<HomeController> _logger;
    private readonly WebApplication2Context _dbcontext;

    public HomeController(ILogger<HomeController> logger, WebApplication2Context context)
    {
        _logger = logger;
        _dbcontext = context;
    }

    public IActionResult Index()
    {
        List<JsonResponse> data = new List<JsonResponse>()
        {
            new JsonResponse(){ PrtgVersion ="20.4.63.1412", TreeSize = 2, devices = new List<Devices>()
            {
                new Devices(){ objid= 40, probe="Local Probe", device = "Probe Device", host = "127.0.0.1"},
                new Devices(){ objid= 41, probe="Local Probe", device = "DNS: 84.116.46.23", host = "86.114.46.23"}
            }
            }
        };
        _dbcontext.JsonResponses.AddRange(data);
        _dbcontext.SaveChanges();
        return View();
    }

Commentaire: Étant donné que l'objet JsonResponse et l'objet Devices contiennent une relation un-à-plusieurs, lorsque vous utilisez le code ci-dessus pour insérer un nouveau JsonResponse, il insérera automatiquement le Devices associé objets dans la table Devices. Pour plus d'informations, consultez la Enregistrement des données associées.

En outre, vous pouvez également utiliser le code suivant pour ajouter un nouveau périphérique dans le tableau Périphériques:

        List<Devices> devicesdata = new List<Devices>()
        {
             //add Devices.
         };
        _dbcontext.Devices.AddRange(devicesdata);
        _dbcontext.SaveChanges();

Référence: Entity Framework Core One To Many Relationships Conventions

Propriétés de navigation

1
Zhi Lv 3 nov. 2020 à 10:07