How can I access the database directly from my model class in an ASP.NET Core project?

1

In ASP.NET Core Mvc I get access to DbContext on the Controller through the _context property represented by my MvcNotaContext class see:

private readonly MvcNotaContext _context;

This way I can search the database in the controller class:

var nota = await _context.Nota.SingleOrDefaultAsync(m => m.ID == id);

However, I have a business rule in my model that needs to get some data directly from the database to perform validation, but I'm not sure how I could get an instance of my MvcNotaContext class directly in my class Nota , and this class needs the DbContextOptions<MvcNotaContext> options configuration options to work, and it is used in the ConfigureServices method in the Startup startup class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddDbContext<MvcNotaContext>(options => options.UseSqlite("Data Source=MvcNota.db"));
}

My template class:

public class Nota: IValidatableObject
{
    public int ID { get; set; }       
    [Required(ErrorMessage="Titulo não pode ficar vazio.")]
    [DataType(DataType.Text)]
    [Display(Name="Título")]
    public string Titulo { get; set; }
    [Required(ErrorMessage="Conteúdo não pode ficar vazio.")]
    [Display(Name="Conteúdo")]
    [DataType(DataType.MultilineText)]
    public string Conteudo { get; set;}

    IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
    {
        //Busca dados na base de dados.
        throw new System.NotImplementedException();
    }
}

Access to the database would occur in the Validate method, respectively.

Question

How can I access the database directly from my model class in an ASP.NET Core MVC project?

    
asked by anonymous 20.11.2017 / 16:59

2 answers

1

You just create a context instance in this method, just as you would any other object

IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext vCtx)
{
    var optBuilder = new DbContextOptionsBuilder<MvcNotaContext>();
    optBuilder.UseSqlite("Data Source=MvcNota.db");
    var context = new MvcNotaContext(optBuilder.Options);
}

Note: I changed the parameter name just to shorten the code.

For this, of course, you need to make sure that there is a constructor of MvcNotaContext that receives an instance of DbContextOptions<T> as a parameter.

public MvcNotaContext(DbContextOptions<MvcNotaContext> options) : base(options) { }
    
22.11.2017 / 16:37
1

Instantiating a context within your model class (which represents a table in the database) is not an interesting standard, the domain obligation is only to validate, and for this you do not need to make a direct instance with the bank. It is not good practice for an inner layer to be coupled to a Work Unit.

If you want to compare a value previously entered in the database with a new object, query before on your chosen layer (I recommend you do this in a service layer) and pass it as an argument to your validation class, something like:

var minhaNotaConsultadaDoBanco = await _context.Nota.SingleOrDefaultAsync(m => m.ID == id);

Now in your model:

IEnumerable<ValidationResult> IValidatableObject.Validate(Nota minhaNotaConsultadaDoBanco)
{
    //Exemplo:
    if(this.Titulo != minhaNotaConsultadaDoBanco.Titulo) { ... }
}

If you want to insert a completely new object and double check, you can use the instance itself to invoke the validation method.

IEnumerable<ValidationResult> IValidatableObject.Validate()
{
    //Exemplo:
    if(this.Titulo != string.Empty) { ... }
}

Call:

minhaNotaConsultadaDoBanco.Validate();
    
20.11.2017 / 18:03