question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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

See original GitHub issue

I can’t verify and test my database by in memory providers. for example I set these properties to required :

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
}

and this is my 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));


    }

And this is my unit test :

[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);
            }

        }
    }

But the unit test method always return 1 and passes, meanwhile the empty object of LogRequest must not save anything to database! How can I determine not null properties for unit test ? In fact how can I enforce unit test to reflect to validation policies ?

Further technical details

EF Core version: 1.1.0 Database Provider: Microsoft.EntityFrameworkCore Operating system: Windows 10 IDE: Visual Studio 2015

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

12reactions
bricelamcommented, Oct 24, 2017

Here is one way to check ValidationAttributes and IValidatableObject by overriding SaveChanges.

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,
                validateAllProperties: true);
        }

        return base.SaveChanges();
    }
}
3reactions
ajcvickerscommented, Dec 12, 2016

@paradisehuman 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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Validating entities using data annotations or fluent api in ...
Going beyond EF to the database, the in-memory database does not currently validate nullability (i.e. requiredness) when saving property values.
Read more >
Data validation - EF6
When using code first, you can specify validations using annotation or fluent API configurations. Additional validations, and more complex, ...
Read more >
[Solved]-Validating entities using data annotations or fluent api in EF ...
Coding example for the question Validating entities using data annotations or fluent api in EF 7.0 (In Memory)-entityframework core.
Read more >
Use FluentValidation in ASP.NET or ASP.NET Core
FluentValidation provides a great alternative to Data Annotations in order to validate models. It gives better control of validation rules and makes validation...
Read more >
ASP.NET Core and FluentValidation: A Practical Guide
FluentValidation offers a compelling alternative to Data Annotations for model validation. It empowers developers with enhanced control over validation rules, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found