0

I'm trying to inserting and updating in this EF6-MVC project, but I cannot do it properly. I really need your help guys, I'd appreciate it.

Let's say I have this 3 tables:

Class/Table 1: Curso --> CursoId - nombreCurso

Class/Table 2: Modalidad --> ModalidadId - nombreModalidad

Class/Table 3: ModalidadCurso --> ModalidadId - CursoId (EF Creates automatically)


Let's get just to the point, next model (simplified):

public class Curso
{
        public int CursoId{ get; set; }

        public string nombreCurso { get; set; }

        public virtual ICollection<Modalidad> Modalidades { get; set; }
}


public class Modalidad
{

        public int ModalidadId{ get; set; }

        public string nombreModalidad { get; set; }

        public virtual ICollection<Curso> Cursos { get; set; }
}



public class ItehlContext: DbContext
{
        public ItehlContext(): base("name=conexionItehl") { }

        public DbSet<Curso> Cursos { get; set; }

        public DbSet<Modalidad> Modalidades { get; set; }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            modelBuilder.Entity<Modalidad>()
             .HasMany(c => c.Cursos)
             .WithMany(i => i.Modalidades)
             .Map(t => t.MapLeftKey("codigoModalidad")
                 .MapRightKey("codigoCurso")
                 .ToTable("ModalidadCurso"));

        }
}

well, the thing is, I'm trying to do the next thing, EF6 is creating a ModalidadCurso table, where saves the ModalidadId & CursoId, as a many-many relationship where pass the FK of the classes.

But I'm having problems in my MVC-ViewForm when I'm trying to create a new Curso Entity, cause it does not create the ForeignKeys in the modalidadCurso entity as it should be expected. I been studing that little inconvenience for days, it simply doesn't work.

Controller Create GET/POST

    // GET: /Curso/Create
    public ActionResult Create()
    {
        var cursos = new Curso();
        cursos.Modalidades = new List<Modalidad>();
        ListaModalidadesDropDownList(cursos);
        return View();
    }

    // POST: /Curso/Create
    // Para protegerse de ataques de publicación excesiva, habilite las propiedades específicas a las que desea enlazarse. Para obtener 
    // más información vea http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include="codigoCurso,nombreCurso")] Curso curso)
    {
        try
        {
            var nuevaModalidad = new List<Modalidad>();
            if (nuevaModalidad != null)
            {

                foreach (var modalidad in nuevaModalidad)
                {
                    var agregarModalidad = db.Modalidades.Find(modalidad);
                    curso.Modalidades.Add(agregarModalidad);

                }
            }

            if (ModelState.IsValid)
            {
                db.Cursos.Add(curso);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
        }

        catch (RetryLimitExceededException /* dex */)
        {
            //Log the error (uncomment dex variable name and add a line here to write a log.)
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
        }

        ListaModalidadesDropDownList(curso.Modalidades.First().codigoModalidad);
        return View(curso);
    }

I got this:

Entity Insert Many-Many-Relationship

And it creates the entity in Curso Table, that's ok.

but, in the FK-Many Many Relationship-ModalidadCurso table, it doesn't do anything.

What am I doing wrong?? I'm a beginner in Entity Framework, but everything seems ok.

Thanks for the help.

This is the Create.cshtml file (simplified)

@model ItehlConsulting.Models.Itehl.Curso
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken() 
   l.ValidationSummary(true)

        <div class="form-group">
            @Html.LabelFor(model => model.nombreCurso, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.nombreCurso)
                @Html.ValidationMessageFor(model => model.nombreCurso)
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" for="codigoModalidad">Modalidad</label>
            <div class="col-md-10">
                @Html.DropDownList("codigoModalidad", String.Empty)
                @Html.ValidationMessageFor(model => model.Modalidades.First().nombreModalidad)
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Crear Curso" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
Fabio
  • 11,892
  • 1
  • 25
  • 41
dato000
  • 13
  • 1
  • 6
  • how does your view looks like ? – Shyju Dec 05 '15 at 15:43
  • Should I post all the view?? Complete Create.cshtml?? – dato000 Dec 05 '15 at 15:53
  • Looks like your opcionModalidades is coming back as an empty collection . Did you put a breakpoint in your code and inspect it ? – Shyju Dec 05 '15 at 15:54
  • Code First is based on naming conventions, at the moment I don't have the naming conventions here but I have noticed that you have your classes without any data annotations, last time that I have used code first I used data annotations in the classes. May be you have to annotate the primary key of the classes. http://www.entityframeworktutorial.net/code-first/key-dataannotations-attribute-in-code-first.aspx The many to many relationship I think that it's correct maped with the fluent API as you do. – JuanDYB Dec 05 '15 at 15:58
  • well, it looks like opcionModalidades is null, how can I correct that?? About DataAnnotations, well my project has a lot of changes about this one, I just simplified according to the conventions, cause I'm using DataAnnotations && DataAnnotations.Schema; for practice. Fluent API well, I have one example, but I don't think is the best way before learning mapping first. – dato000 Dec 05 '15 at 16:07
  • 1
    Where are you sending `opcionModalidades` in your code? it's not in the view? – A. Burak Erbora Dec 05 '15 at 16:18
  • yeah you got right, I was following an example, but I realize that it was using a checkbox, and I'm using a DropList, so I don't need to use "opcionModalidades" my bad, so I modified that, but still I don't get what I want, so let me edit the code. – dato000 Dec 05 '15 at 16:20
  • still not working, and I'm out of ideas. I found something similar in this link, http://stackoverflow.com/questions/4253165/insert-update-many-to-many-entity-framework-how-do-i-do-it but it doesn't work, the edit example looks great, but I can't found something with the create controller. – dato000 Dec 05 '15 at 16:43
  • https://msdn.microsoft.com/en-us/magazine/dn166926.aspx – Gert Arnold Dec 05 '15 at 22:17
  • it doesn't has what I look for, thx anyway – dato000 Dec 06 '15 at 00:33

1 Answers1

0

In your view, you are sending codigoModalidad and nombreCurso. You have to post these values to the controller.

Replace this:

public ActionResult Create([Bind(Include="codigoCurso,nombreCurso")] Curso curso)

for this:

public ActionResult Create(string nombreCurso, int codigoModalidad)

Then, inside your controller action, you have to create the Curso and relate it with Modalidad:

[HttpPost]
public ActionResult Create(string nombreCurso, int codigoModalidad)
{
    Modalidad modalidad = new Modalidad();
    modalidad.ModalidadId = codigoModalidad;
    //if modalidad already exists in database, and you just want to make a relationship
    ctx.Entry(modalidad).State = EntityState.Unchanged; 
    //if modalidad does not exists in database, and you want to insert it
    //ctx.Entry(modalidad).State = EntityState.Added;

    Curso curso = new Curso();
    curso.nombreCurso = nombreCurso;
    curso.Modalidades.Add(modalidad); //add our existing modalidad to our new course

    ctx.Cursos.Add(curso);
    ctx.SaveChanges();
}

EDIT 1

Inside Curso constructor:

public Curso() 
{
    Modalidades = new HashSet<Modalidad>();   
}

Inside Modalidad constructor:

public Modalidad()
{
     Cursos = new HashSet<Curso>();
}

Hope it helps!

Fabio
  • 11,892
  • 1
  • 25
  • 41
  • Thanks fabio, I did what you explain, but still not working, it seems "codigoModalidad" doesn't saving the value of the create.cshtml, I don't know how do that, I tried putting directly the item of the FK. like this: @Html.ValidationMessageFor(model => model.Modalidades.First().codigoModalidad) but I'm getting the NullReferenceException, all of codigoModalidad, maybe if I could get info about how handle many-to-many relationship data with entity with razor webforms, I could do this, but still haven't found the howto I need to do this thing. the MVC guide is great, but I still dont get it. – dato000 Dec 06 '15 at 00:36
  • you are using a dropdown list to represent the modalidad, it means that modalidad is already created in the database when you enter create.cshtml. I see this code `@Html.DropDownList("codigoModalidad", String.Empty)` Why you are passing a "String.Empty" ? you should pass a collection of items – Fabio Dec 06 '15 at 01:12
  • according to the wiki "SelectExtensions.DropDownList Method (HtmlHelper, String)" is only passing a string value of the List, which I'm passing a empty string, The DropDownList is showing nothing in the webform, until is selected, then it shows the List of Modalidades. How can I pass the collection?? – dato000 Dec 06 '15 at 01:39
  • debug the app and see if `nombreCurso` and `codigoModalidad` are being set inside the controller – Fabio Dec 06 '15 at 01:43
  • in the constructor public ActionResult Create(string nombreCurso, string descripcionCurso, string dirigido, double costoCurso, int horasCurso, int codigoModalidad), everything looks fine, but then Modalidad modalidad = new Modalidad(); modalidad.ModalidadId = codigoModalidad; ModalidadID is NOT saving the value, what's happening?? another thing, the DropDownList method is setting for another method outside the controller, ListaModalidadesDropDownList(); which is using LINQ to get the List of information to fill up the DropDownList,don't worry about the GET Create, is POST Create where is prob – dato000 Dec 06 '15 at 02:21
  • it won't save the value, because the code says that `modalidad` object already exists in database. If you want to insert a new modalidad you have to change the state as `Added`. Take a look at my updated answer – Fabio Dec 06 '15 at 06:25
  • still got nullException, it seems when I try to use the property Added or Unchanged, I have to send all the parameters of Modalidad Class, Id, nombreModalidad, descripcionModalidad, you know what I mean, is trying to create a new class, I just need to make a new Curso, with an existed value of Modalidad, take those Related ForeignKeys and save them in the many-to-many table created by default with EF in the database. Thanks anyway for the help Fabio. too bad I can't upload images over here. But I think you understand the problem. – dato000 Dec 07 '15 at 15:43
  • @dato000 I reproduced your problem here, I used the code in my answer and it works fine. Maybe there is another error that you don't see... Try to create a new application with Curso and Modalidad using the code I provided, see if the error still occurs – Fabio Dec 07 '15 at 15:56
  • I tried with new Project "itehl2" same problem --- Línea 60: curso.Modalidades.Add(modalidad); //add our existing modalidad to our new course --- Detalles de la excepción: System.NullReferenceException: Referencia a objeto no establecida como instancia de un objeto. System.NullReferenceException, I got nothing, hey you have skype, wanna help me over there?? camilio.cepeda000 thx I'm still trying with this project. – dato000 Dec 07 '15 at 16:55
  • oohh I see, you have to initialize the collection. See my updated answer. – Fabio Dec 07 '15 at 17:03
  • Absolutely Fantastic!!! you are the man Fabio thanks!!!!!!! how did you knew all that?????? worked like a charm, 11/10 my friend, thank you very much, now I'll do that to the hole project (it has more attributes, but is the same stuff) Fabio, thanks man, again, let me ask you, how did you knew that?? thx!!!! – dato000 Dec 07 '15 at 17:39
  • @dato000 you are welcome mate! Don't forget to mark the post as the correct answer. How did I know? I had all these problems in the past :) – Fabio Dec 07 '15 at 17:44