【问题标题】:Errors trying to Linq join and pass back a ViewModel C# MVC尝试 Linq 加入并传回 ViewModel C# MVC 时出错
【发布时间】:2017-10-10 06:04:00
【问题描述】:

我在尝试在 Linq 中为两个数据库表进行联接时遇到了一些错误。在我的数据库中,我有一个参与者表和一个性别表。 我有 3 个模型在使用 - Participant、Gender 和 ParticipantDetailsViewModel。 (最终我想切换其他参与者的详细信息以允许更多的数据抽象,例如城市表)。

参与者

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MVCManageParticipants.Models
{
    public class Participant
    {
        public int Id { get; set; }
        public int SiteId { get; set; }
        public int Status { get; set; }
        public int Gender { get; set; }
        public string Title { get; set; }
        [Required]
        [StringLength(35)]
        public string Name { get; set; }
        public string City { get; set; }
        public string Postcode { get; set; }
        public string Telephone { get; set; }
        public string Notes { get; set; }
    }
}

性别

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MVCManageParticipants.Models
{
    public class Gender
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

ParticipantDetailsViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MVCManageParticipants.Models
{
    public class ParticipantDetailsViewModel
    {
        public int Id { get; set; }
        public int SiteId { get; set; }
        public int Status { get; set; }
        public string Title { get; set; }
        public string Gender { get; set; }
        public string Name { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Postcode { get; set; }
        public string Telephone { get; set; }
        public string Notes { get; set; }
    }
}

在我的控制器中,我有以下方法来处理详细信息页面:

public ActionResult Details([Bind(Prefix = "id")]int participantId = 0)
        {
            // Check participant exists
            Participant participant = _db.Participants.Find(participantId);

            if (participant == null)
            {
                return HttpNotFound();
            }

            var model = (from p in _db.Participants
                        join g in _db.Genders on p.Gender equals g.Id
                        where p.Id == participantId
                        select new ParticipantDetailsViewModel
                        {
                            Id = p.Id,
                            SiteId = p.SiteId,
                            Status = p.Status,
                            Gender = g.Name,
                            Title = p.Title,
                            Name = p.Name,
                            City = p.City,
                            Postcode = p.Postcode,
                            Telephone = p.Telephone,
                            Notes = p.Notes
                        });

            return View(model);
        }

当我调试应用程序时,我会从控制器返回模型并在结果视图中显示以下内容:

为了测试,我已经剥离了我的详细信息视图,以便我拥有以下内容:

@model MVCManageParticipants.Models.ParticipantDetailsViewModel

@{ ViewBag.Title = "Details"; }

<h2>Details2</h2>
@Model.Id
@Model.Gender

我收到以下错误:

传入字典的模型项的类型为“System.Data.Entity.Infrastructure.DbQuery`1[MVCManageParticipants.Models.ParticipantDetailsViewModel]”,但此字典需要“MVCManageParticipants.Models”类型的模型项.ParticipantDetailsViewModel'。

不知道问题是什么以及如何解决它。

【问题讨论】:

  • model 在您的情况下是一个 LINQ 查询,它可能导致多个实体,而您的视图只需要一个对象作为模型。试试return View(model.FirstOrDefault);
  • 只是一个小笔记。当 EF 专门设计用于帮助您自动执行联接时,我不断看到人们手动执行联接;你可以在你的Participant 上有public Gender Gender {get;set;},如果上下文配置正确,你可以访问它,EF 会在幕后为你加入。因此,在投影中,您可以只使用 Gender = p.Gender.Name 并忘记加入的所有内容。
  • @AlexPaven 您能否提供任何资源来进一步解释这一点?它仍然使用此方法,但性别字段为空。
  • @AlexPaven 表中的新列已创建,名为 Gender_ID,需要填充。感谢您的提示,这更容易更清洁!

标签: c# asp.net-mvc entity-framework linq asp.net-mvc-5


【解决方案1】:

这就是你的行动应该是什么:

public ActionResult Details([Bind(Prefix = "id")]int participantId = 0)
{
    // Check participant exists
    Participant participant = _db.Participants.Find(participantId);

    if (participant == null)
    {
        return HttpNotFound();
    }

    var model = (from p in _db.Participants
                    join g in _db.Genders on p.Gender equals g.Id
                    where p.Id == participantId
                    select new ParticipantDetailsViewModel
                    {
                        Id = p.Id,
                        SiteId = p.SiteId,
                        Status = p.Status,
                        Gender = g.Name,
                        Title = p.Title,
                        Name = p.Name,
                        City = p.City,
                        Postcode = p.Postcode,
                        Telephone = p.Telephone,
                        Notes = p.Notes
                    }).FirstOrDefault();

    return View(model);
}

Where 子句的结果是 Collection 而不是 Single 对象。结果可能是一个包含一个对象的集合,但它仍然是一个集合,而视图需要一个 ParticipantDetailsViewModel 对象而不是它的集合。 FirstOrDefault 只会从前面查询的结果中获取第一个对象(这是您的视图所需要的)

【讨论】:

  • 看起来很有希望,但现在我收到此错误:无法在 LINQ to Entities 查询中构造实体或复杂类型“MVCManageParticipants.Models.ParticipantDetailsViewModel”。
  • ParticipantDetailsViewModel 不是 DbContext 的一部分,对吧?我的意思是它不是实体?
  • 就是这样。看起来它添加了 public System.Data.Entity.DbSet ParticipantDetailsViewModels { get;放; }
【解决方案2】:

首先,您尝试将 IQueryble 传递给您的视图,请尝试在控制器中调用“FirstOrDefault”或将您的模型更改为 List 并在控制器中调用“ToList”。

【讨论】:

    【解决方案3】:

    如果你有返回模型是 List 。

    所以你收到了错误。

    您总是正确的答案,但您的查询会发生微小的变化。

    您使用过 FirstOrDefault 或 SingleOrDefault

    var model = (from p in _db.Participants
                        join g in _db.Genders on p.Gender equals g.Id
                        where p.Id == participantId
                        select new ParticipantDetailsViewModel
                        {
                            Id = p.Id,
                            SiteId = p.SiteId,
                            Status = p.Status,
                            Gender = g.Name,
                            Title = p.Title,
                            Name = p.Name,
                            City = p.City,
                            Postcode = p.Postcode,
                            Telephone = p.Telephone,
                            Notes = p.Notes
                        }).FirstOrDefault();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 1970-01-01
      • 2013-05-31
      • 2018-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多