This is a migrated thread and some comments may be shown as answers.

Working with ManyToMany relations

2 Answers 491 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Mikael
Top achievements
Rank 2
Mikael asked on 17 Feb 2013, 05:31 PM
 I'v finally been able to do som more work with Kendo and have been fiddling more with my ManyToMany relations. I'v set ut a test project with a two really simple models Movies and Actors
[Table("Movies")]
    public class Movie
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int MovieId { getset; }
        public string Name { getset; }
        public List<Actor> Actors { getset; }
    }
And
[Table("Actor")]
    public class Actor
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int ActorId { getset; }
        public string Name { getset; }
        [ScriptIgnore]
        public List<Movie> Movies { getset; }
    }
Code first migrations have kindly generated a ActorMovie table for me in the database and using normal MVC4 controllers and views this is working as expected. I'm able to both add one or more actors to a movie. And add one or movie to an actors.

Now, I would like to be able to display the lists of Actors or Movies in the row of the respective Movie or Actor in a Grid.
I'd also like to be able to add both Actors and Movies (one or more) using an editable Grid.

Since the Grid build up and controllers will be the same for both I'm only going to add the code for the movies.
This is my Grid so far:
@(Html.Kendo().Grid<KendoUi.ViewModels.MovieViewModel>()
    .Name("Grid")
    .Columns(columns =>
    {
        columns.Bound(p => p.MovieId);
        columns.Bound(p => p.Name);
        columns.ForeignKey(p => p.Actors, (System.Collections.IEnumerable)ViewBag.Actors, "ActorId", "Name");
        columns.Command(command => { command.Edit(); command.Destroy(); }).Width(180);
    })
    .ToolBar(toolbar => toolbar.Create())
    .Editable(editable => editable.Mode(GridEditMode.InLine))
    .Pageable()
    .Sortable()
    .Scrollable()
    .DataSource(dataSource => dataSource
        .Ajax()
        .Events(events => events.Error("error_handler"))
        .Model(model =>
            {
                model.Id(p => p.MovieId);
                model.Field(p => p.MovieId).Editable(false);
            })
        .Create(update => update.Action("EditingInline_Create", "Movie"))
        .Read(read => read.Action("EditingInline_Read", "Movie"))
        .Update(update => update.Action("EditingInline_Update", "Movie"))
        .Destroy(update => update.Action("EditingInline_Destroy", "Movie"))
        )
)
And this is my controller:
public class MovieController : Controller
    {
        private readonly KendoContext context;
 
        public MovieController()
        {
            context = new KendoContext();
        }
 
        public ActionResult Index()
        {
            ViewBag.Actors = context.Actors;
            return View();
        }
 
 
        public ActionResult EditingInline_Read([DataSourceRequest] DataSourceRequest request)
        {
            return Json(context.Movies.Include("Actors").ToDataSourceResult(request));
        }
 
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditingInline_Create([DataSourceRequest] DataSourceRequest request, MovieViewModel movie)
        {
            if (movie != null && ModelState.IsValid)
            {
                var toAdd = new Movie() {Name = movie.Name};
                context.Entry(toAdd).State = EntityState.Added;
                context.SaveChanges();
            }
            return Json(new[] { movie }.ToDataSourceResult(request, ModelState));
        }
 
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditingInline_Update([DataSourceRequest] DataSourceRequest request, MovieViewModel movie)
        {
            if (movie != null && ModelState.IsValid)
            {
                var target = context.Movies.Single(x => x.MovieId == movie.MovieId);
                if (target != null)
                {
                    target.Name = movie.Name;
                    context.Entry(target).State = EntityState.Modified;
                    context.SaveChanges();
                }
            }
            return Json(ModelState.ToDataSourceResult());
        }
 
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditingInline_Destroy([DataSourceRequest] DataSourceRequest request, MovieViewModel movie)
        {
            if (movie != null)
            {
                var target = context.Movies.Single(x => x.MovieId == movie.MovieId);
                context.Entry(target).State = EntityState.Deleted;
                context.SaveChanges();
            }
            return Json(ModelState.ToDataSourceResult());
        }
    }
And finally the MovieViewModel(I realize that as the code is now, the MovieViewModel isn't necessary:
public class MovieViewModel
    {
        public int MovieId { get; set; }
        public string Name { get; set; }
        public List<Actor> Actors { get; set; }
    }

Since the logic to add ManyToMany relations are the same for MVC4 controllers using normal Views I assume I'm going to be able to use that code for this too.
I just need som guidance into what changes I need to do to the actual Grid code and ViewModel to be able to retrieve the data needed from the Grid to add/remove objects in the controller.

2 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 20 Feb 2013, 10:21 AM
Hello Mikael,

The foreignkey column can be used for one to many relations. For many to many you could use an Grid Hierarchy or a custom editor that can update a collection of objects(source binding, another list component). 

Regards,
Daniel
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Mikael
Top achievements
Rank 2
answered on 20 Feb 2013, 10:52 AM
Hello, thanks for the tips.
I'll look into them both, since the related table, in this case, only contains a one field I think inserting a whole grid would be overkill.
I haven't looked at building a custom editor yet, but if it could produce a Selectmany style selectbox that would fit perfect.
I'll post back if I run into any problems later.

Br.
Tags
Grid
Asked by
Mikael
Top achievements
Rank 2
Answers by
Daniel
Telerik team
Mikael
Top achievements
Rank 2
Share this question
or