我有一个自定义验证属性,该属性用于防止使用EF Core服务器端在db表中重复输入。下面的代码在为包含字符串值的列(在本例中为MappingName列)分配自定义属性时效果很好-请参见数据库表图像。
如果用户尝试创建另一个系统映射,例如名称为“ Mapping 1”,那么自定义验证属性将向他们发出警告并停止将它们保存到数据库,这很好,但是我需要使用两个外键(整数值而不是字符串)和重复项的相同工作流进行此操作还有它们是外键的事实。
我需要解决的两列是:
ConnectorInboundID = 1 ConnectorOutboundID = 1 (其他表中的外键)
参考以下代码: 使用当前的自定义属性配置,模型类中的“ MappingName”列可以正常运行。
使用相同的自定义属性方法,外键列无法正常工作。
下面的图像仅显示了系统映射数据库表的设计布局:
模型类:
public class SystemMapping
{
public int ID { get; set; } // Primary Key
[Required]
[CheckDuplicate(nameof(ID), ColumnName = "systemMappingName")] // This works well
[Display(Name = "Mapping Name")]
public string MappingName { get; set; }
[Required]
[CheckDuplicate(nameof(ID), ColumnName = "systemMappingInboundConnectorName")] // This does NOT work :(
[Display(Name = "Connector In")]
public int ConnectorInboundID { get; set; }
[Display(Name = "Connector In")]
public ConnectorInbound ConnectorInbound { get; set; }
}
自定义验证属性类:
public class CheckDuplicate : ValidationAttribute
{
private readonly string _IdPropertyName;
public CheckDuplicate(string IdPropertyName)
{
_IdPropertyName = IdPropertyName;
}
public string ColumnName { get; set; }
protected override ValidationResult IsValid(
object value, ValidationContext validationContext)
{
// SystemMapping Model
if (ColumnName == "systemMappingName") // System Mapping Name.
{
// ? is used in case the object 'value' is null.
// This only happens when deleting a row from the database.
string name = value?.ToString();
var property = validationContext.ObjectType.GetProperty(_IdPropertyName);
if (property != null)
{
var idValue = property.GetValue(validationContext.ObjectInstance, null);
var _context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));
var exists = _context.SystemMapping.Any(d => d.MappingName == name && d.ID != int.Parse(idValue.ToString()));
if (exists)
return new ValidationResult("Name already in use...");
return ValidationResult.Success;
}
// SystemMapping Model
if (ColumnName == "systemMappingInboundConnectorName") // Inbound Connector Name.
{
// ? is used in case the object 'value' is null.
// This only happens when deleting a row from the database.
string name = value?.ToString();
//int id = Convert.ToInt32(value); // This didnt work either...
var property = validationContext.ObjectType.GetProperty(_IdPropertyName);
if (property != null)
{
var idValue = property.GetValue(validationContext.ObjectInstance, null);
var _context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));
//var exists = _context.SystemMapping.Any(d => d.ConnectorInboundID == name && d.ID != int.Parse(idValue.ToString()));
var exists = _context.SystemMapping.Any(d => d.ConnectorInboundID == name && d.ID != int.Parse(idValue.ToString()));
if (exists)
return new ValidationResult("Connector already in use...");
return ValidationResult.Success;
}
}
}
我得到的错误警告与以下事实有关:自定义属性代码期望从模型类导入的对象“值”的字符串值,但我确实尝试修改自定义属性代码以更改对象值从字符串到整数,错误消失并允许我运行应用程序,没有任何调试错误,但是我发现在asp.net创建页面上创建新的系统映射时,该页面通常应将我定向到索引页面,其中列出了新添加的项目,但未添加任何内容。
下图显示了如果我尝试对这些外键列使用相同的方法,则会得到错误:
我想找到一个解决方案,使我能够继续使用与普通字符串一样有效的方法,但是将其与整数值和/或可能正在尝试使用外键的事实一起使用正在引起问题。