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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法通过视图访问组合键表,以便在该表中输入数据或分配正确的主键?相关的知识,希望对你有一定的参考价值。

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

我有两个类ActorsMovies有多对多的关系(Actor可以在许多MoviesMovie可以有许多Actors)。

一切正常,但我无法通过视图访问中间(MoviesActors)表(此表是由于ActorsMovies之间的多对多关系而自动生成的)。我想访问这个表,以便我可以分配正确的主键来确定“特定演员有多少部电影?”之类的内容。和“有多少演员在某部电影中扮演过角色?”。

这些是我的模特:

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; }
}

我有两个模型和数据库中的三个表。

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

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

顺便说一下这是控制器:

    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表(用问号检查两个地方),但我无法这样做。

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

提前谢谢了。

这是我的新剃刀观点

    @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>
答案

实体框架隐藏了中间表,但不要担心mvc有ViewModel完成你的工作的神话般的功能,这意味着你可以创建像MoviesActors这样的中间表的视图

因此对于,

1)你必须为你的中间表创建一个视图模型

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)提交表格后,你的邮政方法将添加你的mvzact

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

注意:上面的代码片段适用于一部电影和一部演员。因此,如果你想在单个电影中添加多个演员,那么将你在act中的MoviesActorsViewModel属性更改为Listpublic List<Actors> act { get; set; }并添加multiple textbox in view并在发布你的表单到动作方法之后Create添加像_context.actrs.AddRange(mcvm.act);这样的多个演员

编辑:

我也要注册一个新演员。但是我想从actors表中选择actor并将它们分配给已注册的新电影。

如果你必须在添加新电影的同时为影片分配多个演员

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填充actor以从get view action方法查看模型的act列表

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");
}
另一答案

@Prince_Walizada如你所说,你有第三个表叫做Junction Table,使用EF就不需要访问这个表了。因为您可以直接将任意数量的其他实体添加到当前记录中。

例如(这是伪代码):

 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" , ...}

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

以上是关于无法通过视图访问组合键表,以便在该表中输入数据或分配正确的主键?的主要内容,如果未能解决你的问题,请参考以下文章

无法从 Laravel Vue 通讯录项目中的外键表中获取数据

使用从 VBA 代码派生的值填充表中的字段

尝试在访问错误中查找重复记录

外键约束的作用

分布式解决选择

提交值后无法在表中获取值