无法通过视图访问复合键 table,以便在该 table 中输入数据或分配正确的主键?

Can not access the composite key table through a view, in order to enter data or assign the correct primary key in that table?

我正在尝试使用代码优先方法使用 C# 和 EF 开发 ASP.NET MVC 应用程序。

我有两个 类 ActorsMovies 它们具有多对多关系(一个 Actor 可以在许多 Movies 中,一个Movie 可以有很多 Actors).

一切正常,但我无法通过视图访问中间(MoviesActors)table(此table是多对多自动生成的结果- ActorsMovies 之间的许多关系)。我想访问这个 table 以便我可以分配正确的主键来确定 "How many movies does a particular actor have?" 和 "How many actors have played a role in a particular movie?".

之类的东西

这些是我的模型:

public class Actors
{
    public Actors()
    {
        this.mvz = new HashSet<Movies>();
    }

    public int Id { get; set; }
    public string actor_name { get; set; }
    public string country { get; set; }

    public virtual ICollection<Movies> mvz { get; set; }
}

public class Movies
{
    public Movies()
    {
        this.actz = new HashSet<Actors>();
    }

    public int Id { get; set; }
    public string Movie_title { get; set; }
    public string genre { get; set; }

    public virtual ICollection<Actors> actz { get; set; }
}

我有两个上面的模型和三个table在数据库中。

现在从视图中,我可以访问演员模型和电影模型,但是当涉及到中间模型时 table (MoviesActors),我无法访问它的模型,因为它不存在,这意味着我无法在视图中引用 MoviesActors 并且无法通过表单输入数据。

我想问一下我的方法是否正确,我的意思是在现实世界的应用程序中我们是否必须访问复合键 table 并进行数据输入,或者是否有更好的方法解决这个问题?

顺便说一句,这是控制器:

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

    [HttpPost]
    public ActionResult Add(??? mva)
    {
        _context.act.Add(mva.act);
        _context.mvz.Add(mva.mvz);
        _context.SaveChanges();
        return RedirectToAction("Index","Actors");
    }

这是视图:

  @model Many_To_Many_Relationship_Latest.?.?
  @{
      ViewBag.Title = "DataEntry";
      Layout = "~/Views/Shared/_Layout.cshtml";
  }

在顶部,我应该可以通过 Model 或 ViewModel 访问 MoviesActors table(检查带问号的两个地方),但我无法这样做。

如果有这方面专业知识的人正在阅读这篇文章post,请指导我正确的逻辑或任何其他有助于我获得结果的方法。

非常感谢。

这是我的新剃须刀视图

    @model Many_To_Many_Relationship_Latest.ViewModel.MoviesActorsViewModel

    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
    integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
    crossorigin="anonymous"></script>



         @{
         ViewBag.Title = "DataEntry";
         Layout = "~/Views/Shared/_Layout.cshtml";
         }

         <h5>Enter Data in Movies_Actors Table</h5>

         @using (Html.BeginForm("Add","MoviesActors"))
         {
       <div class="form-group">
       @Html.LabelFor(a=> a.mvz.Movie_title)
    @Html.TextBoxFor(a=> a.mvz.Movie_title, new { @class="form-control"})
</div>
<div class="form-group">
    @Html.LabelFor(a => a.mvz.genre)
    @Html.TextBoxFor(a => a.mvz.genre, new { @class = "form-control" })
</div>



foreach (var item in Model.act)
{
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <div class="checkbox control-group">
                <label>
                    <!-- SEE id property here, I've made it dynamic -->
                    <input type="checkbox" id="cb_@item.Id" value="@item.Id" class="checkBoxClass" />
                    <label>@item.actor_name</label>
                </label>
            </div>
        </div>
    </div>
}

<div>
    <input type="hidden" name="Ids" id="Ids" />
</div>


<button type="submit" class="btn btn-primary">Save</button>
    }




         <div>
@Html.ActionLink("Back to List", "Index")
        </div>

     <script>
$(function () {

    var ids = [];

    $(".checkBoxClass").change(function () {
        if (this.checked) {
            ids.push(this.value);
        }
        else {
            var index = ids.indexOf(this.value);
            ids.splice(index, 1);
        }
        $('#ids').val(ids);
    });


     });
     </script>

@Prince_Walizada 如您所说,您有第三个 table,称为 Junction Table,通过使用 EF,无需访问此 table .因为您可以直接将任意数量的其他实体添加到当前记录中。

例如(这是伪代码):

 var Movie = MyContext.Movies.Where(P=>Title.Contains("Star war")).FirstOrDefault();
 Movie.Actors.Add(new Actor() { Name = "Mike" , ...}
 Movie.Actors.Add(new Actor() { Name = "Joe" , ...}
 Movie.Actors.Add(new Actor() { Name = "Daniel" , ...}

你也可以反过来做:

 var Actor = MyContext.Movies.Where(P=>Name.Contains("Mike")).FirstOrDefault();
 Actor.Movies.Add(new Movie() { Title = "World of War" , ...}
 Actor.Movies.Add(new Movie() { Title = "hobbits" , ...}
 Actor.Movies.Add(new Movie() { Title = "toy story" , ...}

如您所见,您不需要知道第三个 table。

中间 table 被 Entity framework 隐藏了,但是不用担心 mvc 有很棒的功能 ViewModel 来完成你的工作,这意味着你可以为中间 table 喜欢 MoviesActors

因此,

1) 你必须为你的中级 table 创建一个视图模型,比如

public class MoviesActorsViewModel
{
    public MoviesActorsViewModel()
    {
        mvz = new Movies();
        act = new Actors();
    }

    public Movies mvz { get; set; }
    public Actors act { get; set; }
}

2) 为上面的视图模型添加视图,例如

public ActionResult GetView()
{
    MoviesActorsViewModel mcvm = new MoviesActorsViewModel();

    return View(mcvm);
}

3) 然后您对上述操作方法的看法。

以下剃须刀仅供您了解。您的实际剃须刀可能与此不同。

@model WebApplication2.Controllers.MoviesActorsViewModel

@{
    ViewBag.Title = "GetView";
}

<h2>GetView</h2>

@using (Html.BeginForm("Create", "Default", FormMethod.Post)) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>MoviesActorsViewModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        //mvz fields below

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.TextBoxFor(model => model.mvz.movie_title, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.TextBoxFor(model => model.mvz.genre, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>

        //act fields below

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.TextBoxFor(model => model.act.actor_name, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.TextBoxFor(model => model.act.country_of_birth, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>

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

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

4) 提交表单后,您的 post 方法将添加您的 mvzact 喜欢

[HttpPost]
public ActionResult Create(MoviesActorsViewModel mcvm)
{
    _context.mvz.Add(mcvm.mvz);
    _context.actrs.Add(mcvm.act);
    return RedirectToAction("GetView", "Default");
}

注意:以上代码片段是针对一部电影和一位演员。 因此,如果您想将多个演员添加到单部电影中,请将 MoviesActorsViewModel 中的 act 属性 更改为 List 点赞 public List<Actors> act { get; set; } 并添加 multiple textbox in view 并在 post 将您的表单添加到操作方法 Create 之后添加多个参与者,例如 _context.actrs.AddRange(mcvm.act);

编辑:

I have to register a new actor too. But I want to select actors from the actors table and assign them to the new movies that gets registered.

如果在添加新电影时必须为电影分配多个演员,那么

1) 您的视图模型是

public class MoviesActorsViewModel
{
    public MoviesActorsViewModel()
    {
        mvz = new Movies();
        act = new List<Actors>();
    }

    public Movies mvz { get; set; }
    public List<Actors> act { get; set; }
    public string[] ids { get; set; }
}

2) 从 db 填充你的 actors 以从你的 get view action 方法查看模型的动作列表

public ActionResult GetView()
{
    MoviesActorsViewModel mcvm = new MoviesActorsViewModel();
    mcvm.act = _context.actrs.ToList();
    return View(mcvm);
}

3) 在剃须刀视图中,您必须输入一部电影并为其选择多个演员,然后只需为每个演员选中复选框并将其各自的 id 值添加到数组,然后使用表单提交传递该数组.

@model WebApplicationMVC1.Controllers.MoviesActorsViewModel

<script src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>

@{
    ViewBag.Title = "GetView";
}

<h2>GetView</h2>

@using (Html.BeginForm("Create", "Default1", FormMethod.Post))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>MoviesActorsViewModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        //mvz fields below

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.TextBoxFor(model => model.mvz.movie_title, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.TextBoxFor(model => model.mvz.genre, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>

        //act fields below from list of actors

        @foreach (var item in Model.act)
        {
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <div class="checkbox control-group">
                        <label>
                            <!-- SEE id property here, I've made it dynamic -->
                            <input type="checkbox" id="cb_@item.Id" value="@item.Id" class="checkBoxClass" />
                            <label>@item.actor_name</label>
                        </label>
                    </div>
                </div>
            </div>
        }

        <div>
            <input type="hidden" name="ids" id="ids" />
        </div>

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

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

<script>
    $(function () {

        var ids = [];

        $(".checkBoxClass").change(function () {      
            if (this.checked) {                
                ids.push(this.value);
            }
            else {
                var index = ids.indexOf(this.value);
                ids.splice(index, 1);
            }
            $('#ids').val(ids);
        });


    });
</script>

4) 将表单提交到以下操作后,您可以遍历每个 id 演员并将其与电影

一起保存到数据库中
[HttpPost]
public ActionResult Create(MoviesActorsViewModel mcvm)
{
    _context.mvz.Add(mcvm.mvz);

    foreach (var id in mcvm.ids)
    {
        int id1 = Convert.ToInt32(id);
        Actors act = _context.actrs.Find(x => x.Id == id1);
        _context.actrs.Add(act);
    }


    return RedirectToAction("GetView", "Default");
}