【问题标题】:How to get results in View from 3 tables in MVC如何从 MVC 中的 3 个表中获取视图中的结果
【发布时间】:2019-08-10 13:23:26
【问题描述】:

我有3个相关表,Table1 => Table2 => Table3 关系就是这种类型。

我有来自 Table1 和 Table2 的数据,因为我有来自 Table1 的模型要显示,现在我的问题是 Table3,我无法获取要显示的数据。 我需要详细显示数据,我的项目是为民意调查。

  1. 表 1 = 问题(键是 QID)
  2. 表 2 = 答案选项(关键 ANID,q_ID 是问题的关键)
  3. Table3 = 结果(投票计数)(键是 RID,ans_ID 是 AnswerOption 的键)

控制器是默认代码:

 public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }



            Questions questions= db.Questions.Find(id);
            if (questions== null)
            {
                return HttpNotFound();
            }




            return View(questions);
        }

查看代码:

 @foreach (var item in Model.Answers)
        {

            if (item != null)
            {
        <tr>
            <td>
                @Html.DisplayFor(x => item.AnswerName)
            </td>
            <td>
                @Html.DisplayFor(x => item.Results.Result)
            </td>

        </tr>
            }

模型问题:

public class Questions
    {
        public Questions()
        {
            Answers= new HashSet<Answers>();

        }
        [Key]
        public  int QID { get; set; }
        public string Prasanje { get; set; }
        public bool pubOdg { get; set; }
        public int? avtor { get; set; }

        public virtual ICollection<Answers> Answers { get; set; }

       [ForeignKey("avtor")]
        public virtual tbl_useri tbl_useri { get; set; }

    }

模型答案:

 public Answers()
        {
            Results= new HashSet<Results>();
        }

        [Key]
        public int ANID{ get; set; }

        public int q_ID{ get; set; }


        public string Odgovor { get; set; }
        public string kreator { get; set; }
        public int? rCount { get; set; }

        [ForeignKey("q_ID")]
        public virtual Questions Questions{ get; set; }

        public virtual ICollection<Results> Results{ get; set; }

模型结果:

 public class Results
    {
        [Key]
        public int RID{ get; set; }
        public int ans_ID{ get; set; }
        public int Result{ get; set; }


        [ForeignKey("ans_ID")]
        public virtual Answers Answers { get; set; }

    }

【问题讨论】:

  • 提示:不要将 EF 实体对象用作 ViewModel。
  • 您使用实体框架调用db.Questions,它将根据提供的ID构建问题实体。该实体是否有权获得答案? Entity Framework 是否真的构建了那个子对象?
  • 你能把你所有的模型都贴在这里吗?
  • 这个问题远未完成,有很多方法可以做到这一点(MVC、MVVM 模式、存储库、UoW)我认为目前无法回答,而且可能永远不会很好,因为试图回答它会暴露代码在理解方面缺少其他主要缺陷的地方(EF 连接、联合、交叉应用、自动映射器......)
  • 一些研究建议,实体框架很强大,但您定义了上下文,以便它可以映射到您的实体。但是前端或视图数据通常并不代表实体或数据聚合,因此您通常需要映射或扩展将数据转换为前端视图的方式。

标签: c# .net asp.net-mvc entity-framework model-view-controller


【解决方案1】:

我将从一些定义开始:

  • view-model 是一种表示特定于特定渲染视图的数据的类型。控制器动作应该创建这个对象并用加载的数据填充它,然后将它传递给视图。
    • 这是 ASP.NET MVC 和 ASP.NET Core 中关注点分离的核心,也是所有现代(2005 年后)Web 编程框架中的常见设计模式。
    • 将其与旧式 PHP/CGI/Classic ASP 编程相比较,您可以将数据库代码与 HTML 混合使用。
    • 在 Web 编程中,视图模型通常是一个不可观察、不可变和短暂的对象,仅在 HTTP 请求的生命周期内持续存在。而在桌面编程(如 WPF、UWP XAML 等)中,视图模型通常是可观察的、可变的和长期存在的)。
  • model 类(与 view-model 不同)或 entity 类是表示来自您的后备存储数据库的数据的对象. (忽略 Razor 使用关键字 @model 来表示视图模型这一事实。

(令我失望和恼火的是,大多数 ASP.NET MVC 和 ASP.NET Core 的初学者级教程仍然向用户介绍使用 Entity Framework 实体类型作为视图模型的反模式。这些教程应该教给读者使用单独的视图模型以避免像此 OP 那样引导读者走错路和最终造成混淆。使用 EF 实体作为视图模型也会导致安全问题,因为它允许恶意用户重置其他用户的密码(例如)如果输入请求的验证不充分(例如,[BindNever] 的用途)。我的意思是:不要。)

回到正题:

如果这是一个单向视图(即您只显示数据库中的数据而不允许用户在&lt;form&gt; 中编辑该数据),则定义一个新类作为您的视图模型并填充它您的实体数据作为属性。

在你的情况下,你的控制器操作是QuestionsController::Details,所以我有这个:

public class DetailsViewModel
{
    // One-way members:

    [BindNever]
    public String PageTitle { get; internal set; }

    public Question TheQuestion  { get; internal set; }

    public List<Answer> TheAnswers { get; internal set; }

    // Two-way members:

    // (you don't have any forms, so this area is empty)
}

然后修改您的控制器操作以创建、填充并返回此视图模型类型:

public async IActionResult Details(Int32? id)
{
    if( id == null ) return this.NotFound();

    Question question = await this.db.Questions.SingleOrDefaultAsync( id.Value );
    if( question == null ) return this.NotFound();

    DetailsViewModel vm = new DetailsViewModel()
    {
        PageTitle = "Details for " + question.Title,
        TheQuestion = question,
        TheAnswers = await this.db.Answers.Where( q => a.Question == question ).ToListAsync()
    };

    return this.View( model: vm );
}

并更改您的 Razor 视图以使用此视图模型:

@model DetailsViewModel

<html>
<head>
<title>@Model.PageTitle</title>
</head>
<body>

<h2>Question</h2>

<p>@Model.TheQuestion.QuestionText</p>

<h2>Answers</h2>

@foreach( Answer ans in this.Model.TheAnswers )
{
<h3>Answer @ans.Name</h3>

    @foreach( Result result in ans.Results )
    {
<h3>@result.Name</h3>
    }
}

</body>
</html>

如果您想允许用户在POST 中编辑&lt;form&gt; 中的数据,那么您需要为您希望用户能够编辑的每个表行定义新的类。但这超出了您最初问题的范围,请在线搜索“ASP.NET mvc 模型绑定”了解更多详细信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-07
    • 2012-12-31
    • 2017-11-12
    • 2018-04-06
    • 2021-01-07
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多