在 EF Code First 中访问导航属性时出错

Posted

技术标签:

【中文标题】在 EF Code First 中访问导航属性时出错【英文标题】:Error while accessing the Navigation Property in EF Code First 【发布时间】:2011-09-13 22:13:22 【问题描述】:

我有一个简单的 ViewModel,它有这样的东西......

视图模型

public class UserPostCommentViewModel
    

        public virtual List<Comment> Comment  get; set; 

        public virtual User User  get; set; 

        public virtual Post Post  get; set; 
    

这样我就可以返回一个视图,其中包含 1 个帖子,其中包含 1 个用户详细信息和用户提交的许多评论....

发布

 [Key]
        [ScaffoldColumn(true)]
        public int PostID  get; set; 

        [Required(ErrorMessage="Required")]
        [StringLength(250)]
        public string Title  get; set; 

        [Required(ErrorMessage="Required")]
        [DataType(DataType.MultilineText)]
        public string Body  get; set; 

        [DataType(DataType.Date)]
        public DateTime DateCreated  get; set; 

        [DataType(DataType.Date)]
        public DateTime DateModified  get; set; 

        [ScaffoldColumn(false)]
        public int UserID  get; set; 

        [ScaffoldColumn(false)]
        public int? TagID  get; set; 

        public virtual ICollection<Comment> Comments  get; set; 

        public virtual User Users  get; set; 

        public virtual ICollection<Tag> Tags  get; set; 

评论

[Key]
        [ScaffoldColumn(true)]
        public int CommentID  get; set; 

        [DisplayName("Your Comment")]
        [DataType(DataType.MultilineText)]
        public string Body  get; set; 

        [DataType(DataType.Date)]
        [ScaffoldColumn(true)]
        public DateTime DateCreated  get; set; 

        [ScaffoldColumn(true)]
        public int PostID  get; set; 

        [ScaffoldColumn(true)]
        public int UserID  get; set; 

        public User User  get; set; 

        public Post Posts  get; set; 

用户

[ScaffoldColumn(true)]
        [Key]
        public int UserID  get; set; 

        [StringLength(15)]
        [DisplayName("First Name")]
        [Required(ErrorMessage="First Name is Required")]
        public string FirstName  get; set; 

        [StringLength(15)]
        [DisplayName("Last Name")]
        [Required(ErrorMessage = "Last Name is Required")]
        public string LastName  get; set; 

        [DataType(DataType.EmailAddress,ErrorMessage="please enter valid email")]
        [DisplayName("Email Address")]
        [Required(ErrorMessage = "Email is Required")]
        [Remote("CheckUniqueEmail","User",ErrorMessage="An account with this email address already exists.")]
        public string Email  get; set; 

        [DataType(DataType.Password)]
        [Required(ErrorMessage = "Password is Required")]
        public string Password  get; set; 

        [DataType(DataType.Date)]
        [ScaffoldColumn(true)]
        public DateTime JoiningDate  get; set; 

        [DataType(DataType.Date)]
        [ScaffoldColumn(true)]
        public DateTime? LastActivityDate  get; set; 

        public virtual ICollection<Post> Posts  get; set; 

        public virtual ICollection<Comment> Comments  get; set; 

        public virtual ICollection<Tag> Tags  get; set; 

我有一个带有 ViewModel 的 StronglyTyped 视图,因此我可以在一个视图中返回所有三个模型属性...

但是 :( 我想在该特定帖子的每个评论前面显示用户名而不是用户 ID。所以我在视图模型中使用 ICollection cmets,以便我可以返回 cmets 的集合。当我尝试像这样访问用户名属性@Model.Comments.User.LastName // OR Email // OR FirstName .. 我收到编译错误。我不能这样使用,因为它是一个集合类型...

如何使用 cmets 中提供的用户 ID 从 cmets 实体中检索用户名..

请帮忙...

通过添加部分视图来完成所有工作..

_评论部分视图..

在我的局部视图中,我添加了这样的...

==========================

@
    ContextRepository db = new ContextRepository();
    var userID = Model.UserID;
    var userName = db.EUser.Find(userID).FirstName;   


【问题讨论】:

【参考方案1】:

您可以创建一个局部视图来显示评论并在主视图的循环中调用它。

帖子详情视图

@model UserPostCommentViewModel
@
    ViewBag.Title = "Post";
    Layout = "~/Views/Shared/_Layout.cshtml";


@foreach (Comment comment in Model.Comments)

    @Html.Partial("_Comment", comment);

_评论部分视图

@model Comment

<div class="comment">
    <div class="desc">@Model.Body</div>

    <div class="submitted-by">@Model.User.LastName</div>
</div>

模型问题

您需要将导航属性设为虚拟才能延迟加载。

public class Comment

    //other properties

    public virtual User User  get; set; 

    public virtual Post Posts  get; set; 

如果您要访问这些导航属性,那么您需要预先加载它们。否则你会遇到Select n+1 问题。使用Include 方法预加载属性

var post = db.Posts.Include(p => Comments)
            .Include(p => p.Comments.Select(c => c.User))
            .Where(p => p.PostID == 1).Single();

【讨论】:

嘿..谢谢...我试过这个并得到以下错误...对象引用未设置为对象的实例。说明:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。异常详细信息:System.NullReferenceException:对象引用未设置为对象的实例。

@Model.User.FirstName 它是一个空引用异常...
嗯...我用过这样的东西,现在它的工作...虽然从你的回答中学到了新方法..谢谢分享+1

以上是关于在 EF Code First 中访问导航属性时出错的主要内容,如果未能解决你的问题,请参考以下文章

EF Code First 导航属性 与外键

在使用 EF 4.1 Code-First 的 Include 和/或 Select 方法时订购导航属性?

没有导航属性的EF Code First外键

EF Code First导航属性一对一关系中注意点及配置方法

EF5.X Code First表关联与延迟加载

EF4 Code First & SQLCE 4.0 - 生成数据库时出现异常