entity-framework - EF Code First 将外键插入/更新限制为给定的 ReferenceType
问题描述
对 EF Code First 来说相当新,并试图锻炼如何做我通常用触发器做的事情。我想创建一个参考表,其中包含给定系统中不同下拉列表和选择框的各种项目。参考表布局如下:
ReferenceId Guid
ReferenceType string
Key string
value object
我想为状态代码、性别类型、用户提出的任何多项选择等项目存储键/值。在允许插入/更新之前,我想在不同的表上设置一个外键,以便在引用表中存在键/值。我过去在 Database First SQL 中通过创建外键然后添加触发器来限制属于特定 ReferenceType 的允许键/值来完成此操作。
据我所知,您没有使用 EF Code First 的触发器,所以我想我需要检查给定表的外键 id 属性的 set 方法,以确保该值是给定的ReferenceType 在引用表中,如果没有则抛出异常。我正在考虑引用表模型中的一个方法,另一个表模型中的 set 方法可以调用传递 ReferenceType 和 Key,如果有效,则返回 ReferenceId,否则返回 null 并引发异常。
我的问题是,这是否是处理此类情况的正确方法,或者 EF 中是否有另一种我没有看到的方法来执行此操作?
目前为 Net Core 2.2 编码
解决方案
通过使用自定义验证属性弄清楚了。发现我需要同时覆盖SaveChanges()
和SaveChangesAsync()
在我的 DBContext 中。添加了对以下方法的调用:
private void ValidateEntities()
{
var entities = (from entry in ChangeTracker.Entries()
where entry.State == EntityState.Modified || entry.State == EntityState.Added
select entry.Entity);
var validationResults = new List<ValidationResult>();
foreach (var entity in entities)
{
var validationContext = new ValidationContext(entity);
Validator.ValidateObject(entity, validationContext, true);
}
}
这使我可以申请以下ValidationAttribute
课程:
using System;
using System.ComponentModel.DataAnnotations;
using DataAccess.Models;
namespace DataAccess.Data.Attributes
{
/// <summary>
/// Valid Reference Attribute
/// </summary>
/// <revision>
/// __Revisions:__~~
/// | Contributor | Build | Revison Date | Description |~
/// |-------------|-------|--------------|-------------|~
/// | Christopher D. Cavell | 0.3.0 | 09/16/2019 | Initial commit |~
/// </revision>
public sealed class ValidGenderTypeAttribute : ValidationAttribute
{
private Guid validGuid = Constants.GenderTypeId;
/// <summary>
/// Validate ReferenceTypeId
/// </summary>
/// <param name="value">object</param>
/// <param name="validationContext">ValidationContext</param>
/// <returns>ValidationResult</returns>
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
if (value is Reference)
{
Reference reference = (Reference)value;
if (reference.ReferenceTypeId == validGuid)
return ValidationResult.Success;
return new ValidationResult($"Invalid GenderTypeID: {reference.ReferenceTypeId.ToString()}");
}
return new ValidationResult($"Invalid object type: {value.GetType().ToString()}");
}
return ValidationResult.Success;
}
}
}
像这样对我的模型:
/// <value>Guid</value>
public Guid? GenderId { get; set; }
/// <value>Reference</value>
[ForeignKey("GenderId")]
===> [ValidGenderType]
public Reference Gender { get; set; }
推荐阅读
- r - 如何在 R 中使用 ggplot2 用抖动点覆盖平均值和误差条并平滑分布?
- php - Ninja forms - 如何在感谢页面上向用户显示提交的数据?
- python-3.x - 删除所有零条目的嵌套列表元素
- firebase - 我们应该允许用户直接上传到 Google Firebase 存储吗?
- javascript - 使用 JQuery 更改单击按钮的背景颜色不起作用
- python - Pytest 在测试后花费的时间最多?
- android - Android Room:离线缓存不起作用
- ruby-on-rails - Shopify API 如何通过 Shopify API Gem 更新库存水平
- python - 我找不到元素,但在手动检查元素后,代码可以工作
- c - X11 剪贴板:Window 的属性是什么?