开发者

How to update tables with a many-to-many join with a bridging table that has payload

I am building a personal Movie Catalogue and have the following structure:

Movie table/entity

MovieID (PK identifier) + Other movie related properties

Person table/entity

PersonID (PK identifier) + Other person related properties.

PersonMovie table/entity

MovieID (FK)

PersonID (FK)

Other columns containing information about what the person did on t开发者_StackOverflowhe movie (I.e. charactor name or job).

I want to have a view that allows a user to create/update a movie, or a person, and have a checkbox to then allow them to select existing or create new cast members (persons), or movies.

I am struggling on two fronts: 1) how to present this type of multi-page data collection. A movie has many cast members & a person can be involved in many movies. 2) how to update 2 or 3 of the tables above depending on what the user whats to enter. A user may want to add a movie but doesnt know the cast members yet or vice versa. A user may want to add a movie and add people who already exist as cast members of the movie.

Also I do not want cascading deletes and have struggled switching it off for the relationships between the above entities.

I can do this easily with webforms but am learning MVC 3 & Entity Framework 4 and am still getting my head around it all. I have looked around and haven't come across solutions/tutorials on what I would like to achieve.

Any help would be much appreciated. Tony


I had a similar issue when I switched from another MVC framework (Rails as in ROR). For the starters, check out Leniency's reply on the similar question, that is; relationship-with-payload or non-PJT (pure-join-table) which unfortunately ASP.NET MVC3 doesn't support explicitly.

You can create a ModelView (a virtual entity) to wrap the collections of other entity types and pass it to the View. The aforementioned post has the detailed example with the code for Model, ViewModel, View, Partial and the Controller. (read both the answers on that post, my answer is continuation of Leniency's answer there)

Hope it helps!


Vulcan's on the right track, and my response that she linked too will help you get the model setup where the linking table contains extra data.

For building the views, you'll mostly likely find that ViewModels are the way to go for more complicated setup like you're describing, then your controller and service layer will deal with processing the view model data and translating it into EF entities. Viewmodels are built specifically to the view that you need, rather than trying to hammer a domain model into a view that may not fit it.

Here's a very rough start for one of the workflows for creating a movie, with an optional list of people.

Domain - your Movie and Person class, plus a linking table similar to what I described here.

View Models - Create a movie and attach people to it

public class MovieCreatePage
{
    public MovieInput Input { get; set; }  // Form field data...
    public IEnumerable<People> People { get; set; } // list of people for drop downs
    // ... other view data needed ...
}

public class MovieInput
{
    [Required, StringLength(100)]
    public string Name { get; set; }

    // Easiest to just submit a list of Ids rather than domain objects.
    // During the View Model -> Domain Model mapping, there you inflate them.
    public int[] PeopleIds { get; set; }

    // ... other input fields ...
}

Create.cshtml - just make a form for your view model.

Controller:

// NOTE! The parameter name here matches the property name from the view model!
// Post values will come across as 'Input.Name', 'Input.Year', etc...
// Naming the parameter the same as the view model property name will allow
// model binding.  Otherwise, you'll need an attribute: [Bind(Prefix=".....")]
[HttpPost]
public ActionResult Create(MovieInput input)
{
    if (ModelState.IsValid)
    {
        //
        // Now do your mapping - I'd suggest Automapper to help automate it,
        // but for simplicity, lets just do it manually for now.

        var movie = new Movie
        {
            Name = input.Name,
            Actors = input.PeopleIds != null
                ? input.PeopleIds.Select(id => new Person { Id = id })
                : null
        };

        //
        // Now save to database.  Usually in a service layer, but again,
        // here for simplicity

        // First, attach the actors as stubbed entities
        if (movie.Actors != null)
        {
            foreach (var actor in movie.Actors)
                _db.People.Attach(actor);  // Attach as unmodified entities
        }

        _db.Movies.Add(movie);
        _db.SaveChanges();

        TempData["Message"] = "Success!"; // Save a notice for a successful action
        return RedirectToAction("Index");
    }

    // Validation failed, display form again.
    return View(new MovieCreatePage
    {
        Input = input,
        // ... etc ...
    });
}

Hopefully this helps you some and points you in a good direction. It does, of course, bring up a lot of other questions that will just take time (ie, automapper, service layers, all the various EF gotcha's, etc...).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜