c# - MVC 保存到两个表
问题描述
项目有两张桌子。它需要从传感器到数据库的值。如何保存到两个有关系的数据库?代码可能是错误的。也许有人可以帮忙。
public class Assets
{
public int id { get; set; }
public int? sensorid { get; set; }
public int? value { get; set; }
public DateTime? DateTime { get; set; }
public virtual Sensors Sensors { get; set; }
}
和
public class Sensors
{
public int id { get; set; }
public int? sensorname { get; set; }
public virtual ICollection<Assets> Assets { get; set; }
}
控制器
public ActionResult Index(Sensors sensors, Assets assets)
{
int[] response = client.ReadHoldingRegisters(StartAddress, quantity);
client.Disconnect();
Assets asst = new Assets();
Sensors sns = new Sensors();
for (int i = 0; i < quantity; i++)
{
asst.value = response[i];
sns.id = StartAddress;
db.Assets.Add(asst);
for (int x = 0; x < 3; x++)
{
db.Sensors.Add(sns);
}
db.SaveChanges();
}
解决方案
首先,如果您仍然能够更改标识符的名称,我的建议是坚持实体框架编码约定。这样做可以让您和其他人更容易理解您的代码。
我建议的更改之一是对单个项目使用单数名词,对集合使用复数名词。在这种情况下,我们将有一个资产类,而您的 DbContext 将有一个资产的 DbSet。
除此之外,你的一段代码使用了很多变量,我们必须猜测它们是什么以及它们的功能是什么:StartAddress、数量、客户端、db。使用大写坚持一个约定:StartAddress 是一个变量吗?或者它是一个类名?
回到你的问题
从您的代码中,我看到传感器和资产之间存在不那么标准的一对多关系。每个Sensor有零个或多个Asset,每个Asset最多可以属于一个Sensor,即属性SensorId所指的那个。如果 SensorId 为 null,则资产不属于任何 Sensor。
如果不是这种情况,但每个资产只属于一个传感器,则考虑将属性 SensorId 的类型更改为int
而不是int?
. 这样就不可能添加不属于任何资产的传感器。
从您的代码中,我收集到 aClient
有一个 function ReadHoldingRegisters
。此方法返回一个整数数组。数组的长度可能等于数量的值。唉,你没有提到这是否总是如此。
StartAddres 表示现有 Sensor 的 ID。我知道传感器存在于数据库中,否则它不会有 ID。所以我不确定你为什么要四次添加同一个传感器。如果它已经在数据库中,您不必再添加它,如果不是,您应该添加它而不给它一个 ID。在这种情况下,SaveChanges 将确保 Sensor 获得一个 Id。
传感器已经存在
您不必再将传感器添加到数据库中,您只需添加一些资产,每个响应一个资产。
Asset.Value 等于对应的 Response 值,每个 Asset 都属于 Sensor,主键等于 StartAddress。外键 SensorId 指的是这个 Sensor,所以 SensorId 需要设置为 StartAddress。
int[] assetValues = client.ReadHoldingRegisters(startAddress, quantity);
// for every assetValue create an Asset with Value equal to assetValue
// and a foreign key equal to startAddress:
var assetsToAdd = assetValues
.Select(assetValue => new Asset()
{
Value = assetValue,
SensorId = startAddress,
});
using (var dbContext = new MyDbContext(...))
{
// Add the Assets in one call to DbSet.AddRange(IEnumerable)
dbContext.Assets.AddRange(assetsToAdd);
// and save the changes:
dbContext.SaveChanges();
}
如果您对序列使用正确的标识符和正确的复数形式,对单个项目使用单数形式,您是否看到您的代码变得多么容易?
传感器还不存在
在这种情况下,您必须添加一个传感器。不能分配主键,所以不能填写 Asset.SensorId。幸运的是,实体框架足够聪明,可以为您解决这个问题:
int[] assetValues = client.ReadHoldingRegisters(startAddress, quantity);
using (var dbContext = new MyDbContext(...))
{
// Add one Sensor with all its Assets in one go
dbContext.Sensors.Add(new Sensor()
{
// fill the Sensor properties that you know.
// don't fill the Id
...
Assets = assetValues
.Select(assetValue => new Asset()
{
Value = assetValue,
// no need to fill SensorId, Entity framework will do that for you
... // if needed: fill other Asset properties
})
.ToList(),
});
dbContext.SaveChanges();
}
如果需要,您可以分两步执行此操作:
using (var dbContext = new MyDbContext(...))
{
// Add one Sensor without Assets
var addedSensor = dbContext.Sensors.Add(new Sensor()
{
// fill the Sensor properties that you know.
// don't fill the Id, nor property Assets
...
});
// Add the Assets in one call to DbSet.AddRange(IEnumerable)
dbContext.Assets.AddRange(assetValues.Select(assetValue => new Asset()
{
Value = assetValue,
Sensor = addedSensor,
}));
dbContext.SaveChanges();
}
推荐阅读
- javascript - 基于条件的jquery
- riscv - 想澄清我对R型指令的理解
- php - Youtube API - 上传视频
- javascript - 覆盖不会在点击时触发
- apache-kafka - 每次启动时强制自动缩放的消费者阅读整个 Kafka 主题
- android - CustomView 中的 DialogFragment 导致内存泄漏
- java - 如何为使用 ActiveMQ Artemis 的服务编写集成测试
- powerbi - PowerBi 与 ConnectionString
- c# - Windows Server 2019 上 IIS 上的 ASP.NET 应用程序更新
- node.js - 如何在 Node.js 快速路由上显示从外部 URL 获取的图像