在 Aspnet Core 中加载元数据



我正在使用AspNet Core在MVC模板中构建一个项目。

我使用了实体框架,并且已经搭建了现有数据库的基架。现在,我想向某个类添加一些数据注释,但我不想编辑由基架自动生成的类,所以我尝试使用元数据和覆盖现有方法,saveChanges.

用户.cs由基架自动生成

public partial class Users
{
public int UserId { get; set; }
...
// If I have [MaxLength(5, ErrorMessage = "Too short")] here, it works
public string Email { get; set; }
}

UsersMetadata.cs(也尝试了Users.Metadata.cs否则,没有任何变化)

[ModelMetadataType(typeof(UsersModelMetaData))]
public partial class Users { }
public class UsersModelMetaData
{
[MaxLength(5, ErrorMessage = "Too short")]
public string Email { get; set; }
}

MyContext : DbContext class

public override int SaveChanges()
{
var entities = from e in ChangeTracker.Entries()
where e.State == EntityState.Added
|| e.State == EntityState.Modified
select e.Entity;
foreach (var entity in entities)
{               
var validationContext = new ValidationContext(entity);
Validator.ValidateObject(entity, validationContext, validateAllProperties: true);
}
return base.SaveChanges();
}

因此,即使这似乎是正确的解决方案(我整个早上都在搜索),它也不起作用:问题似乎是UsersModelMetaData中的数据注释没有被读取,因为如果我将数据注释直接放在Users.cs文件中,方法saveChanges()将抛出异常。

我确实找到了这个解决方案-> https://stackoverflow.com/a/30127682/6070423 <-但它基于AspNet,并且使用AspNet Core我无法使用AssociatedMetadataTypeTypeDescriptionProvider

知道我该如何解决这个问题吗?

所以,在我 ASP.Net Core论坛上提问后,多亏了Edward Z的回答,我确实找到了一种方法来让它工作。

基本上,我没有使用 ModelMetadataType 创建一个分部类,而是创建了一个包含所有需要验证的属性的类(因此,我将为基架创建的每个类提供一个此类类)。像这样的东西。

// Class generated by scaffolding
public partial class Users
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
}
// Class I did create. Notice that the name could be anything
//   but should contain at least "Users", which is the name of
//   the table generated by scaffolding.
// Also notice that isUnique is a Custom Attribute I've wrote.
public class UsersMetaData
{
[MinLength(2, ErrorMessage = " too short")]   
public string UserName { get; set; }
[MinLength(2, ErrorMessage = " too short psw")]
public string Password { get; set; }
[IsUnique(ErrorMessage = "Email already exists")]
public string Email { get; set; }            
}

之后,我创建了一个映射器,它将由基架自动生成的类的实例映射到我渴望的相对类。像这样:

public static object MapEntity(object entityInstance)
{
var typeEntity = entityInstance.GetType();
var typeMetaDataEntity = Type.GetType(typeEntity.FullName + "MetaData");
if (typeMetaDataEntity == null)
throw new Exception();
var metaDataEntityInstance = Activator.CreateInstance(typeMetaDataEntity);
foreach (var property in typeMetaDataEntity.GetProperties())
{
if (typeEntity.GetProperty(property.Name) == null)
throw new Exception();
property.SetValue(
metaDataEntityInstance,
typeEntity.GetProperty(property.Name).GetValue(entityInstance));
}
return metaDataEntityInstance;
}

请注意,在第一行中,从实例的类型(即 Users)开始,我检索我创建的相应类,方法是向该名称添加字符串"元数据"。然后,我所做的只是创建一个 UserMetaData 类的实例,分配与 Users 实例相同的值。

最后,什么时候调用这个映射器?在保存更改()中,当我进行验证时。这是因为验证是在 UserMetaData 类上进行的。

public override int SaveChanges()
{
var entities = from e in ChangeTracker.Entries()
where e.State == EntityState.Added
|| e.State == EntityState.Modified
select e.Entity;
foreach (var entity in entities)
{
var metaDataEntityInstance = EntityMapper.MapEntity(entity);
var validationContext = new ValidationContext(metaDataEntityInstance);
Validator.ValidateObject(
metaDataEntityInstance,
validationContext,
validateAllProperties: true);
}
return base.SaveChanges();
}

这有点棘手,但一切都有效!

最新更新