Is it correct to save multiple entities at the same time in the ASP.NET MVC Controller?

Asked

Viewed 898 times

7

I need to save 12 entities in the same method, in the Controller, I don’t know if I’m doing it right.

In my method Create of Controller, call all entities and add all attributes in the same View. By clicking the save button, you are saving normally. I wonder if this is the right way? If it is not, I would like to know which is the best.

Remembering that this is just a simple application, where it will not contain much information. Will only be used to not scan new forms.

My Action:

public ActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Animal animal, Atividade atividade, Comunicacao comunicacao, Educacao educacao,
     Especie especie, EstruturaPropriedade estruturaPropriedade, Informacao informacao, Poco poco, ProdutorRural produtorRural,
    Propriedade propriedade, Questionario questionario, Saude saude)
{
    if (ModelState.IsValid)
    {
        db.Animais.Add(animal);
        db.Atividades.Add(atividade);
        db.Comunicacoes.Add(comunicacao);
        db.Educacoes.Add(educacao);
        db.Especies.Add(especie);
        db.EstruturaPropriedades.Add(estruturaPropriedade);
        db.Infomacoes.Add(informacao);
        db.Pocos.Add(poco);
        db.ProdutorRurals.Add(produtorRural);   
        db.Propriedades.Add(propriedade);
        db.Questionarios.Add(questionario);
        db.Saudes.Add(saude);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(propriedade);
}

And in the View, I call the attributes through the Foreign key. I won’t post all the code, because it’s 213 attributes, and it would be hard to understand, by the size of the code, but I’ll put a part.

Entity:

public class Propriedade
    {
        [Key]
        public int iPropriedadeID { set; get; }
        [Required(ErrorMessage = "Digite o nome do Proprietário")]
        public string sProprietario { get; set; }
        public string sSexo { get; set; }
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
        public DateTime? dtNasc { get; set; }
        public string sTelefone { get; set; }
        public string sCelular { get; set; }
        public string sEndereco { get; set; }
        public int? iRg { get; set; }
        public string sUfrg { get; set; }
        public string sCpf { get; set; }
        public string sCpts { get; set; }
        public string sSerieCtps { get; set; }
        public string sNomePropriedade { get; set; }
        public int? iInscricaoMunicipal { get; set; }
        public bool bRegPropriedade { get; set; }
        public string sCartorio { get; set; }
        public string sMtricula { get; set; }
        public string sLivro { get; set; }
        public int? iArea { get; set; }
        public int? iAreaRegistrada { get; set; }
        public int? iAreaTotal { get; set; }
        public bool bIncra { get; set; }
        public string sNumIncra { get; set; }
        public string sNirf { get; set; }
        public string sInscricaoImobiliaria { get; set; }
        public string sDistrito { get; set; }
        public int? iTempoOcupacao { get; set; }
        public string sLocalX { get; set; }
        public string sLocalY { get; set; }

        public virtual ProdutorRural ProdutorRural { get; set; }
        public virtual Animal Animal{ get; set; }
        public virtual Atividade Atividade { get; set; }
        public virtual EstruturaPropriedade EstruturaPropriedade  { get; set; }

To View to save has 2300 lines, then I will post the start, and follow this table base until the end:

<div class="row">
            <div class="col-md-2">
                Nome do Proprietário:
            </div>
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.sProprietario, new {@class = "form-control", style = "width:5000px", placeholder = "Nome Completo"})
            </div>
        </div>
        <hr>
        @*-------------------------------------------------------LINHA 2-----------------------------------------------------------------------------*@

        <div class="row">
            <div class="col-md-2">
                Sexo:
            </div>
            <div class="col-md-3">
                @Html.DropDownListFor(model => model.sSexo, new SelectList(
                    new[]
                    {
                        new {Value = "Masculino", Text = "Masculino"},
                        new {Value = "Feminino", Text = "Feminino"},
                    },
                    "Value",
                    "Text"
                    ), new {@class = "form-control", style = "width: 150px;"})
            </div>
            <div class="col-md-2">
                Data de Nascimento:
            </div>
            <div class="col-md-5">
                @Html.EditorFor(model => model.dtNasc, new { placeholder = "Ex: 20/02/2014"})
                @Html.ValidationMessageFor(model => model.dtNasc)
            </div>
        </div>
        <hr>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Salvar" class="btn btn-default"/>
            </div>
        </div>
  • There are "n" better ways to do it, greatly affecting its implementation. So I don’t know if that would be a good question. It is complex/comprehensive and difficult to answer, and will probably end/end up being debated.

  • @Renan, specifying a little more, I will have some future problem with this form?

  • If you put two ways to do this insertion in your question and you ask which of these two ways is most recommended/best, it is easier to answer. But the way it is, a lot of people would respond in a lot of ways and probably wouldn’t have an answer.

1 answer

11


I will base my answer by not mentioning a correct way, but a way performative how to do this.

I see this with severe concern:

public ActionResult Create(Animal animal, Atividade atividade, Comunicacao comunicacao, Educacao educacao,
     Especie especie, EstruturaPropriedade estruturaPropriedade, Informacao informacao, Poco poco, ProdutorRural produtorRural,
    Propriedade propriedade, Questionario questionario, Saude saude) { ... }

Not that I’m wrong, but this makes maintenance absurdly difficult, since the programmer will have to figure out how to work the Binding complete form.

The performative way to do this is by specifying a Viewmodel that contains all properties that are entities:

public class FormularioViewModel 
{
    public Animal Animal { get; set; }
    public Atividade Atividade { get; set; }
    public Comunicacao Comunicacao { get; set; }
    public Educacao Educacao { get; set; }
    public Especie Especie { get; set; }
    public EstruturaPropriedade EstruturaPropriedade { get; set; }
    public Informacao Informacao { get; set; }
    public Poco Poco { get; set; }
    public ProdutorRural ProdutorRural { get; set; }
    public Propriedade Propriedade { get; set; }
    public Questionario Questionario { get; set; }
    public Saude Saude { get; set; }
}

Viewmodels are not persisted. They are only anemic classes used to organize and validate your form. Viewmodels, when they implement IValidatableObject, behave in a manner identical to a Model, including updating the ModelState of Controller.

With this, the headline of Action of your Controller would be as follows:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(FormularioViewModel viewModel) { ... }

And the View:

    <div class="row">
        <div class="col-md-2">
            Nome do Proprietário:
        </div>
        <div class="col-md-10">
            @Html.TextBoxFor(model => model.Animal.Proprietario, new {@class = "form-control", style = "width:5000px", placeholder = "Nome Completo"})
        </div>
    </div>
    <hr>
    @*-------------------------------------------------------LINHA 2-----------------------------------------------------------------------------*@

    <div class="row">
        <div class="col-md-2">
            Sexo:
        </div>
        <div class="col-md-3">
            @Html.DropDownListFor(model => model.Animal.Sexo, new SelectList(
                new[]
                {
                    new {Value = "Masculino", Text = "Masculino"},
                    new {Value = "Feminino", Text = "Feminino"},
                },
                "Value",
                "Text"
                ), new {@class = "form-control", style = "width: 150px;"})
        </div>
        <div class="col-md-2">
            Data de Nascimento:
        </div>
        <div class="col-md-5">
            @Html.EditorFor(model => model.Animal.DataNascimento, new { placeholder = "Ex: 20/02/2014"})
            @Html.ValidationMessageFor(model => model.Animal.DataNascimento)
        </div>
    </div>
    <hr>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Salvar" class="btn btn-default"/>
        </div>
    </div>

To Action to persist data would look like this:

if (ModelState.IsValid)
{
    db.Animais.Add(viewModel.Animal);
    db.Atividades.Add(viewModel.Atividade);
    db.Comunicacoes.Add(viewModel.Comunicacao);
    db.Educacoes.Add(viewModel.Educacao);
    db.Especies.Add(viewModel.Especie);
    db.EstruturaPropriedades.Add(viewModel.EstruturaPropriedade);
    db.Infomacoes.Add(viewModel.Informacao);
    db.Pocos.Add(viewModel.Poco);
    db.ProdutorRurals.Add(viewModel.ProdutorRural);   
    db.Propriedades.Add(viewModel.Propriedade);
    db.Questionarios.Add(viewModel.Questionario);
    db.Saudes.Add(viewModel.Saude);

    db.SaveChanges();
    return RedirectToAction("Index");
}

return View(propriedade);

Also, using this approach, you can target your View in Partials, sort of like this:

@Html.Partial("_Animal", Model.Animal)
@Html.Partial("_Atividade", Model.Atividade)
@Html.Partial("_Comunicacao", Model.Comunicacao)
...

So she wouldn’t have 2300 lines.

  • 1

    the part of putting my View in Partials I was elaborating last night. Already the Viewmodel for this purpose I had not seen yet. I will implement today. Thanks for your help

Browser other questions tagged

You are not signed in. Login or sign up in order to post.