.net 部分类中的数据自动化,数据库优先方法
我喜欢在单独的分部类中定义数据验证的数据自动化,而不是EF生成的分部类。 我尝试在部分类中构建元数据类,如下所示:.net 部分类中的数据自动化,数据库优先方法,.net,validation,entity-framework-core,.net,Validation,Entity Framework Core,我喜欢在单独的分部类中定义数据验证的数据自动化,而不是EF生成的分部类。 我尝试在部分类中构建元数据类,如下所示: public partial class PersonViewModel { public string Fname { get; set; } } [MetadataType(typeof(PersonViewModelMetaData))] public partial class PersonViewModel { } public class PersonVie
public partial class PersonViewModel
{
public string Fname { get; set; }
}
[MetadataType(typeof(PersonViewModelMetaData))]
public partial class PersonViewModel
{
}
public class PersonViewModelMetaData
{
[Required]
public string Fname { get; set; }
}
顺便说一句,这个方法不起作用,没有数据验证!
我想这可能是因为在创业课上遗漏了一些东西:
以下是文件:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
//DI
services.AddDbContext<HomeSunSystem>(
option => option.UseSqlServer(Configuration.GetConnectionString("xxx")));
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(option=>
{
option.LoginPath = "/Login";
}
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Login}/{action=Index}/{id?}");
});
}
}
}
公共类启动
{
公共启动(IConfiguration配置)
{
配置=配置;
}
公共IConfiguration配置{get;}
//此方法由运行时调用。请使用此方法将服务添加到容器中。
public void配置服务(IServiceCollection服务)
{
services.AddControllersWithViews();
//DI
services.AddDbContext(
option=>option.UseSqlServer(Configuration.GetConnectionString(“xxx”));
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(选项=>
{
option.LoginPath=“/Login”;
}
);
}
//此方法由运行时调用。请使用此方法配置HTTP请求管道。
public void配置(IApplicationBuilder应用程序、IWebHostEnvironment环境)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
其他的
{
app.UseExceptionHandler(“/Home/Error”);
//默认的HSTS值为30天。您可能希望在生产场景中更改此值,请参阅https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(端点=>
{
endpoints.MapControllerRoute(
名称:“默认”,
模式:“{controller=Login}/{action=Index}/{id?}”);
});
}
}
}
及
公共类程序
{
公共静态void Main(字符串[]args)
{
CreateHostBuilder(args.Build().Run();
}
公共静态IHostBuilder CreateHostBuilder(字符串[]args)=>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder=>
{
webBuilder.UseStartup();
});
}
这是.net核心项目
我错过了什么吗?据我所知,
MetadataTypeAttribute
在.NETCore中不起作用。查看以获取有关此的更多信息
使用Microsoft.AspNetCore.Mvc.ModelMetadataType
,而不是使用Metadata
attributem:
[ModelMetadataType(typeof(PersonViewModelMetaData))]
public partial class PersonViewModel
{
}
这适用于MVC验证,但请记住,如果模型位于不同的程序集中,则不起作用
EF Core的一个解决方案可能是
首先创建一个Mapper
类:
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;
}
然后重写DbContext
的SaveChanges
和savechangesync
方法:
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();
}
据我所知,
MetadataTypeAttribute
在.NETCore中不起作用。查看以获取有关此的更多信息
使用Microsoft.AspNetCore.Mvc.ModelMetadataType
,而不是使用Metadata
attributem:
[ModelMetadataType(typeof(PersonViewModelMetaData))]
public partial class PersonViewModel
{
}
这适用于MVC验证,但请记住,如果模型位于不同的程序集中,则不起作用
EF Core的一个解决方案可能是
首先创建一个Mapper
类:
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;
}
然后重写DbContext
的SaveChanges
和savechangesync
方法:
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();
}
如果您坚持在.NET Core上使用MetadataType,可以尝试以下方法: 实体类:
namespace MyProject.Persistence
{
public partial class User
{
public int UserId { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string PasswordHashKey { get; set; }
public byte Role { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CreatedUtc { get; set; }
public DateTime LastUpdateUtc { get; set; }
}
}
ModelMetadataType:将那些需要验证的属性放在接口中,并在分部类中从接口驱动实体类
namespace MyProject.Persistence
{
[ModelMetadataType(typeof(IUserMetadata))]
public partial class User : IUserMetadata
{
public string FullName => FirstName + " " + LastName;
}
public interface IUserMetadata
{
[JsonProperty(PropertyName = "Id")]
int UserId { get; set; }
[JsonIgnore]
string Password { get; set; }
[JsonIgnore]
string PasswordHashKey { get; set; }
[JsonIgnore]
byte Role { get; set; }
}
}
如果您坚持在.NET Core上使用MetadataType,可以尝试以下方法: 实体类:
namespace MyProject.Persistence
{
public partial class User
{
public int UserId { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string PasswordHashKey { get; set; }
public byte Role { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CreatedUtc { get; set; }
public DateTime LastUpdateUtc { get; set; }
}
}
ModelMetadataType:将那些需要验证的属性放在接口中,并在分部类中从接口驱动实体类
namespace MyProject.Persistence
{
[ModelMetadataType(typeof(IUserMetadata))]
public partial class User : IUserMetadata
{
public string FullName => FirstName + " " + LastName;
}
public interface IUserMetadata
{
[JsonProperty(PropertyName = "Id")]
int UserId { get; set; }
[JsonIgnore]
string Password { get; set; }
[JsonIgnore]
string PasswordHashKey { get; set; }
[JsonIgnore]
byte Role { get; set; }
}
}
您所说的数据自动化是什么意思?所有编程都是数据自动化。数据验证不是由EF执行的,它是一个单独的.NET命名空间,与应用程序堆栈(WinForms、WPF、MVC、Razor、Web API)一起使用。验证程序和消息由UI显示,而不是EF。DTO和模型由堆栈验证,而不是EF。您的代码不包含验证属性或方法。如果要使属性成为必需的,请添加
required
属性。检查。验证失败的DTO不会自动导致异常,您必须检查其验证状态事实上,该分部类不是我的,只是从网络中复制它,让您了解我所说的分离元数据的意思。我使用了[Required]和[MinLentgh(3)],但它们在实践中并不影响我的数据验证。没有错误,但也没有数据验证。为什么不在OnModelCreating中通过ModelBuilder使用Fluent API呢。这样做,您的验证与实体类分离。@majid shahabfar我知道这是另一种方式。但是为什么这个代码不起作用呢?您所说的数据自动化是什么意思?所有编程都是数据自动化。数据验证不是由EF执行的,它是一个单独的.NET命名空间,与应用程序堆栈(WinForms、WPF、MVC、Razor、Web API)一起使用。验证程序和消息由UI显示,而不是EF。DTO和模型由堆栈验证,而不是EF。您的代码不包含验证属性或方法。如果要使属性成为必需的,请添加required
属性。检查。验证失败的DTO不会导致exc