如何解决如何将数据从外部API存储到我的MS SQL数据库中
我正在尝试从外部API提取数据,并使用实体框架将此数据保存在MS sql数据库中。我是实体框架的新手,无法弄清楚如何使数据持久化。根据以下模型,遵循“代码优先”原则创建数据库:
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; }
}
我设法从JSON中的API成功接收了数据,将其反序列化并将其添加到List <JsonResponse> dataG
中。现在,我希望通过将其保存到EF数据库来使这些数据持久化。由于我的JsonResponse
包含Devices
对象的列表,因此我在如何做到这一点上苦苦挣扎。我从外部API中提取数据的控制器如下所示:
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);
}
API的JSON数据如下:
{
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,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; }
}
}
编辑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,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);
}
解决方法
您好,这是我的第一个答案,我正在学习英语,我会尝试做得更好。
您有两个桌子吗?掌握细节?
我建议您首先组织代码并分离职责,首先需要具有Dto Object来表示JSON对象以及将数据插入数据库中的实体,然后分离方法,但是我将与您当前的实体共享解决方案
首先,您需要具有包含实体和连接字符串的DbContext,并带有EntityFrameworkCore的DbContext示例:
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; }
}
如果您具有主要详细信息,则需要使用外键创建导航属性,在这种情况下,我将在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; }
}
要保存数据,您需要添加主体实体,详细信息将自动保存:
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);
}
}
}
如果您没有主要详细信息,并且需要保存一系列数据,则必须使用AddRange,并将所有数据保存在一个操作中:
public async Task<ActionResult> Test()
{
JsonResponse data = GetJsonData();
db.Devices.AddRange(data.Devices);
db.SaveChanges();
return View(data);
}
,
正如marc_s所说,EF核心支持访问许多不同的数据库,您使用的是哪种数据库?
通常,要通过EF核心将新数据插入数据库,可以使用DbContext.Add
方法或DbContext.AddRange
方法添加新项目。您可以查看以下文章:EF core Saving data。
我假设您使用的是MS SQL Server数据库,根据您的描述,JsonResponse
和Devices
对象包含one-to-Many relationship,因此您可以使用导航属性,而不是Devices[]
,请尝试如下更改代码:
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; }
}
然后,在迁移并在数据库中生成相关表之后,您可以参考以下代码将新项目插入数据库:
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,device = "DNS: 84.116.46.23",host = "86.114.46.23"}
}
}
};
_dbcontext.JsonResponses.AddRange(data);
_dbcontext.SaveChanges();
return View();
}
注释:由于JsonResponse
对象和Devices
对象包含一对多关系,因此在使用上述代码插入新的JsonResponse
时,它将自动插入相关的{{ 1}}对象放入“设备”表中。有关更多详细信息,请检查Saving Related Data。
此外,您还可以使用以下代码将新设备添加到“设备”表中:
Devices
参考:Entity Framework Core One To Many Relationships Conventions
,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; }
}
更新控制器
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,host")
)
{
string apiResponse = await response.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<JsonResponse>(apiResponse);
db.JsonResponses.Add(data);
db.SaveChang();
}
}
return View(dataG);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。