我的数据库中有两个表:
配置(父级)
id(PK)
姓名
配置警报(子级)
id(PK)
ConfigurationId(PK、FK 配置)
留言
我已经通过 scaffolding 使用自定义模板生成了 Entity Framework Core 的模型:
public partial class Configuration
{
public int Id { get; set; }
public string Name { get; set; } = null!;
public virtual ICollection<ConfigurationAlert> ConfigurationAlerts { get; set; } = new List<ConfigurationAlert>();
}
public partial class ConfigurationAlert
{
public int Id { get; set; }
public int? ConfigurationId { get; set; }
public string Message{ get; set; }
public virtual Configuration ConfigurationIdNavigation { get; set; } = null!;
}
客户端(Angular 应用程序)我通过 HTTP 调用检索所有配置及其警报,该调用到达服务器并使用 EF 上下文查询数据库并返回实体。 ConfigurationAlert 实体返回到客户端而无需 ConfigurationIdNavigation,这对我来说没问题。
问题是,当我将修改后的 Configurations+ConfigurationAlerts 发送回服务器时,出现错误“发生一个或多个错误:ConfigurationAlerts[0].ConfigurationIdNavigation - ConfigurationIdNavigation 字段为必填项。”
我可以使用自定义模板解决使 ConfigurationIdNavigation 可为空的问题:
public virtual Configuration? ConfigurationIdNavigation { get; set; } = null!;
但我认为这不是正确的解决方案,所以我正在寻找建议。
我是否应该复制创建 ConfigurationViewModel 和 ConfigurationAlertViewModel 的实体并将它们用作 DTO? (还有很多其他模型,所以代码会很多)
或者?
提前谢谢您。
我应该复制创建 ConfigurationViewModel 的实体并 ConfigurationAlertViewModel 并将它们用作 DTO? (有很多的 其他型号,所以代码会很多)
嗯,根据您共享的代码片段,您的描述是正确的,使
ConfigurationIdNavigation
可为空并不是理想的解决方案,因为它引入了潜在的数据完整性问题。
根据场景,两种方式都可以解决。
首先,您可以将 ConfigurationIdNavigation 属性包含在查询中,而不是在检索数据时排除它。这可确保填充导航属性并避免保存更改时出现错误。所以我们可以这样做:
var configurations = _context.Configurations
.Include(c => c.ConfigurationAlerts)
.ToList();
您可以考虑的另一种方法是使用视图模型或 DTO(数据传输对象)。因为,它将数据库模型与 API 合约解耦,从而可以更好地控制向客户端发送和从客户端接收的数据。虽然它可能涉及一些额外的代码,但它提供了诸如提高灵活性、减少有效负载大小和增强安全性等优点。
为了实现这一点,我们可以这样做:
public class ConfigurationViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<ConfigurationAlertViewModel> ConfigurationAlerts { get; set; }
}
public class ConfigurationAlertViewModel
{
public int Id { get; set; }
public string Message { get; set; }
}
注意: 请记住,在向客户端发送数据时,请将数据库实体映射到视图模型。另外,当从客户端接收数据时,在保存视图模型之前将它们映射回数据库实体。请参阅此官方文档以获取更多资源。