在 EF 7.0(内存中)中使用数据注释或 fluent api 验证实体

Validating entities using data annotations or fluent api in EF 7.0 (In Memory)

我无法通过内存提供程序验证和测试我的数据库。 例如,我将这些属性设置为必需的:

public abstract class Log
{
    #region Properties
    public Guid Id { get; set; }
    [Required]
    public string ClientIp { get; set; }
    [Required]
    public string Application { get; set; }
    [Required]
    public string Host { get; set; }
    [Required]
    public string Path { get; set; }
    [Required]
    public string Method { get; set; }
    [Required]
    public string User { get; set; }
    [Required]
    public string Date { get; set; }
    #endregion
}

这是我的 DBContext:

public class ApplicationDbContext : IdentityDbContext<ApplicationUsers, Role, Guid>, IUnitOfWork
{
    private readonly IConfigurationRoot _configuration;

    public ApplicationDbContext(IConfigurationRoot configuration)
    {
        _configuration = configuration;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var useInMemoryDatabase = _configuration[key: "UseInMemoryDatabase"].Equals(value: "true",
            comparisonType: StringComparison.OrdinalIgnoreCase);
        if (useInMemoryDatabase)
            optionsBuilder.UseInMemoryDatabase();
        else
            optionsBuilder.UseSqlServer(
                connectionString: _configuration[key: "ConnectionStrings:ApplicationDbContextConnection"]
                , sqlServerOptionsAction: serverDbContextOptionsBuilder =>
                {
                    var minutes = (int) TimeSpan.FromMinutes(3).TotalSeconds;
                    serverDbContextOptionsBuilder.CommandTimeout(commandTimeout: minutes);
                });
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Log>()
            .HasKey(c => c.Id);
        modelBuilder.Entity<Log>()
            .HasDiscriminator<int>(name: "Type")
            .HasValue<LogRequest>(value: Convert.ToInt32(value: LogLevel.Information))
            .HasValue<LogError>(value: Convert.ToInt32(value: LogLevel.Error));


    }

这是我的单元测试:

[TestClass]
public class LogRepositoryTest
{


  private readonly IServiceProvider _serviceProvider;
    public LogRepositoryTest()
    {
        var services = new ServiceCollection();
        services.AddScoped<IUnitOfWork, ApplicationDbContext>();
        services.AddScoped<ILogRepository, LogRepository>();
        services.AddSingleton(provider => new ConfigurationBuilder()
            .AddInMemoryCollection(initialData: new[]
            {
                new KeyValuePair<string, string>(key: "UseInMemoryDatabase", value: "true"),

            })
            .Build());
         services.AddEntityFrameworkInMemoryDatabase().AddDbContext<ApplicationDbContext>(ServiceLifetime.Scoped);
        _serviceProvider = services.BuildServiceProvider();
    }
    [TestMethod]
    public async Task Verify_SaveRequestLog()
    {
        using (var serviceScope = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            using (var context = serviceScope.ServiceProvider.GetRequiredService<IUnitOfWork>())
            {
                context.Set<Log>().Add(new LogRequest());
                var result =await context.SaveAllChangesAsync();
                Assert.AreEqual(1, result);
            }

        }
    }

但是单元测试方法总是return1并通过,同时LogRequest的空对象不能保存任何东西到数据库! 如何确定单元测试的非空属性?事实上,我如何执行单元测试以反映验证策略?

更新:

基于此链接: Entity Framework Core Issues

我问了,我得到了这个回复:

EF Core doesn't do any validation of entities beyond what is needed for internal consistency. Validation is something that could be done in EF, but experience shows that it is not something that is useful to many developers because it usually cannot replace either client-side validation or database validation and there are also other places where validation can be done more effectively.

Going beyond EF to the database, the in-memory database does not currently validate nullability (i.e. requiredness) when saving property values. I will leave this issue open so that we can discuss as a team whether this is something we should add.

Also, if the intent is test with an in-memory database as an approximation for a relational database, then you might want to consider using SQLite in in-memory mode. See https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/index for more information.

基于此链接: Entity Framework Core Issues

我问了,我得到了答案:

class MyContext : DbContext
{
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);
    }

    return base.SaveChanges();
}
}