asp.net mvc的页面未显示相关的,从对象的属性 [英] asp.net mvc page is not showing properties from associated objects

查看:153
本文介绍了asp.net mvc的页面未显示相关的,从对象的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下简单的结构:
申请人
Possition
ApplicantPosition
和ApplicantPositionHistory

I have the following simple structure: Applicant Possition ApplicantPosition and ApplicantPositionHistory

第3类与申请人一个参考和一个与位置。
第四届表有ApplicantPosition一个参考

The 3rd class has one reference with Applicant and one with Position. The 4th table has one reference with ApplicantPosition

在我做展示,每个位置申请人历史上拉松页,我想说明申请人例如:

In the razon page I am doing to show the history of an applicant per position, I want to show the name of the applicant for example

我有这样的HTML,但它给我看空的,那只能说明我是在同一个对象的字段,例如评论信息和datemodified。

I have this in the html, however its showing me empty, it only shows me info for fields that are in the same object, for example comments and datemodified.

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Position.name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.oldStatus.status)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.newStatus.status)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.comments)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.dateModified)
        </td>

我的模型是这样的:

My model is like this:

namespace Data.Model
{

    public class Position
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]   
        public int PositionID { get; set; }

        [Required(ErrorMessage = "Position name is required.")]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Name should not be longer than 20 characters.")]
        [Display(Name = "Position name")]              
        public string name { get; set; }

        [Required(ErrorMessage = "Number of years is required")] 
        [Display(Name = "Number of years")]
        [YearsValidationAttribute(5, ErrorMessage = "{0} value must be greater than {1} years.")]        
        public int yearsExperienceRequired { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }
    }

    public class Applicant
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]      
        public int ApplicantID { get; set; }

        [Required(ErrorMessage = "Name is required")] 
        [StringLength(20, MinimumLength = 3, ErrorMessage="Name should not be longer than 20 characters.")]
        [Display(Name = "First and LastName")]
        public string name { get; set; }

        [Required(ErrorMessage = "Telephone number is required")] 
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Telephone should not be longer than 20 characters.")]
        [Display(Name = "Telephone Number")]
        public string telephone { get; set; }

        [Required(ErrorMessage = "Skype username is required")] 
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Skype user should not be longer than 20 characters.")]
        [Display(Name = "Skype Username")]
        public string skypeuser { get; set; }

        public byte[] photo { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }


    }

    public class ApplicantPosition
    {
        [Key]
        [Column("ApplicantID", Order = 0)]
        public int ApplicantID { get; set; }

        [Key]
        [Column("PositionID", Order = 1)]
        public int PositionID { get; set; }

        public virtual Position Position { get; set; }

        public virtual Applicant Applicant { get; set; }

        [Required(ErrorMessage = "Applied date is required")] 
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date applied")]     
        public DateTime appliedDate { get; set; }

        [Column("StatusID", Order = 0)]
        public int StatusID { get; set; }

        public Status Status { get; set; }

        //[NotMapped]
        //public int numberOfApplicantsApplied
        //{
        //    get
        //    {
        //        int query =
        //             (from ap in Position
        //              where ap.Status == (int)Status.Applied
        //              select ap
        //                  ).Count();
        //        return query;
        //    }
        //}
    }


    public class Address
    {
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Country should not be longer than 20 characters.")]
        public string Country { get; set; }

        [StringLength(20, MinimumLength = 3, ErrorMessage = "City  should not be longer than 20 characters.")]
        public string City { get; set; }

        [StringLength(50, MinimumLength = 3, ErrorMessage = "Address  should not be longer than 50 characters.")]
        [Display(Name = "Address Line 1")]     
        public string AddressLine1 { get; set; }

        [Display(Name = "Address Line 2")]
        public string AddressLine2 { get; set; }   

    }



    public class ApplicationPositionHistory
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int ApplicationPositionHistoryID { get; set; }

        public ApplicantPosition applicantPosition { get; set; }

        [Column("oldStatusID")]
        public int oldStatusID { get; set; }

        [Column("newStatusID")]
        public int newStatusID { get; set; }

        [ForeignKey("oldStatusID")]
        public Status oldStatus { get; set; }

        [ForeignKey("newStatusID")]
        public Status newStatus { get; set; }

        [StringLength(500, MinimumLength = 3, ErrorMessage = "Comments  should not be longer than 500 characters.")]
        [Display(Name = "Comments")]
        public string comments { get; set; }

        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date")]     
        public DateTime dateModified { get; set; }
    }

    public class Status
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int StatusID { get; set; }

        [StringLength(40, MinimumLength = 3, ErrorMessage = "Status  should not be longer than 20 characters.")]
        [Display(Name = "Status")]
        public string status { get; set; }

    }



}

控制器动作

public ViewResult History(int applicantId, int positionId)
        {
            var history= unitOfWork.ApplicantPositionHistoryRepository.Find(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId);
            return View(history);
        }

编辑
UnitofWork.cs

EDIT UnitofWork.cs

公共类的UnitOfWork
    {
        私人HRContext语境=新HRContext();

public class UnitOfWork { private HRContext context = new HRContext();

    private BaseRepository<Position> positiontRepository;
    private BaseRepository<ApplicantPosition> applicantpositiontRepository;
    private BaseRepository<Applicant> applicantRepository;
    private BaseRepository<Status> statusRepository;
    private BaseRepository<ApplicationPositionHistory> applicantPositionHistoryRepository;


    public BaseRepository<ApplicationPositionHistory> ApplicantPositionHistoryRepository
    {
        get
        {

            if (this.applicantPositionHistoryRepository == null)
            {
                this.applicantPositionHistoryRepository = new BaseRepository<ApplicationPositionHistory>(context);
            }
            return applicantPositionHistoryRepository;
        }
    }

    public BaseRepository<Status> StatusRepository
    {
        get
        {

            if (this.statusRepository == null)
            {
                this.statusRepository = new BaseRepository<Status>(context);
            }
            return statusRepository;
        }
    }

    public BaseRepository<Applicant> ApplicantRepository
    {
        get
        {

            if (this.applicantRepository == null)
            {
                this.applicantRepository = new BaseRepository<Applicant>(context);
            }
            return applicantRepository;
        }
    }

    public BaseRepository<Position> PositionRepository
    {
        get
        {

            if (this.positiontRepository == null)
            {
                this.positiontRepository = new BaseRepository<Position>(context);
            }
            return positiontRepository;
        }
    }

    public BaseRepository<ApplicantPosition> ApplicantPositionRepository
    {
        get
        {

            if (this.applicantpositiontRepository == null)
            {
                this.applicantpositiontRepository = new BaseRepository<ApplicantPosition>(context);
            }
            return applicantpositiontRepository;
        }
    }

    public void Save()
    {
        context.SaveChanges();
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

HRContext.cs

HRContext.cs

 public class HRContext : DbContext
    {
        public DbSet<Position> Positions { get; set; }
        public DbSet<Applicant> Applicants { get; set; }
        public DbSet<ApplicantPosition> ApplicantsPositions { get; set; }
        public DbSet<ApplicationPositionHistory> ApplicationsPositionHistory { get; set; }
        public DbSet<Status> Status { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Position>().ToTable("Position");
            modelBuilder.Entity<Applicant>().ToTable("Applicant");
            modelBuilder.Entity<ApplicantPosition>().ToTable("ApplicantPosition");
            modelBuilder.Entity<ApplicationPositionHistory>().ToTable("ApplicationsPositionHistory");
            modelBuilder.Entity<Status>().ToTable("Status");

            modelBuilder.Entity<Position>().Property(c => c.name).IsRequired();
            modelBuilder.Entity<Applicant>().Property(c => c.name).IsRequired();
            modelBuilder.Entity<ApplicantPosition>().Property(c => c.appliedDate).IsRequired();
            modelBuilder.Entity<ApplicationPositionHistory>().Property(c => c.ApplicationPositionHistoryID).IsRequired();
            modelBuilder.Entity<Status>().Property(c => c.StatusID).IsRequired();

            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
            base.OnModelCreating(modelBuilder);
        }
    }

BaseRepository.cs

BaseRepository.cs

public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        internal HRContext context;
        internal DbSet<TEntity> dbSet;

        public BaseRepository(HRContext context)
        {
            this.context = context;
            this.dbSet = context.Set<TEntity>();
        }

        public virtual TEntity GetByID(object id)
        {
            return dbSet.Find(id);
        }


        public virtual void Insert(TEntity entity)
        {
            dbSet.Add(entity);

        }

        public virtual void Delete(object id)
        {
            TEntity entityToDelete = dbSet.Find(id);
            Delete(entityToDelete);
        }

        public virtual void DeleteAll(List<TEntity> entities)
        {
            foreach (var entity in entities)
            {
                this.Delete(entity);
            }
        }

        public virtual List<TEntity> GetAll()
        {
            return context.Set<TEntity>().ToList();
        }

        public virtual void Delete(TEntity entityToDelete)
        {
            if (context.Entry(entityToDelete).State == EntityState.Detached)
            {
                dbSet.Attach(entityToDelete);
            }
            dbSet.Remove(entityToDelete);
        }

        public virtual void Update(TEntity entityToUpdate)
        {
            dbSet.Attach(entityToUpdate);
            context.Entry(entityToUpdate).State = EntityState.Modified;
        }

        public IQueryable<TEntity> Find(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate)
        {
            return dbSet.Where(predicate);
        }
    }

IRepository.cs

IRepository.cs

public interface IRepository<TEntity>
    {
        IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);

        void Insert(TEntity entity);

        void Delete(TEntity entity);

        void DeleteAll(List<TEntity> entities);
    }

我改变了通用的存储库,改变了控制器的操作方法与此:

I changed the generic repository and changed the controller action method with this:

public ViewResult History(int applicantId, int positionId)
{
    //var history= unitOfWork.ApplicantPositionHistoryRepository.Find(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId);
     var history= db.ApplicationsPositionHistory.Include("ApplicantPosition").SingleOrDefault(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId);

    return View(history);
}

但是我得到这个异​​常:

However I am getting this exception:

传递到字典中的模型产品类型Data.Model.ApplicationPositionHistory',但这需要字典类型的'System.Collections.Generic.IEnumerable`1 [Data.Model.ApplicationPositionHistory]'的典范项目。

The model item passed into the dictionary is of type 'Data.Model.ApplicationPositionHistory', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Data.Model.ApplicationPositionHistory]'.

推荐答案

如何实现你的ApplicantPositionHistoryRepository的Find方法?如果是像

How is the Find method of your ApplicantPositionHistoryRepository implemented ? If it is something like

return entities.ApplicantPosition.SingleOrDefault(expression)

然后您必须启用的预先加载是这样的:

return entities.ApplicantPosition.Include("Applicant").SingleOrDefault(expression)

顺便说一句,这就是为什么我个人不喜欢这些通用资料库的原因 - 有总是在你需要贪婪加载你心中已,而且情况下,当它仅仅是浪费资源的情况。在非一般库中,您将只需创建两种方法

Btw this is the reason why I personally dont like these "generic" repositories - there are always situations where you need eager load somethins, and also situations when it is just wasting of resources. In "non-generic" repository you would just create two methods

GetApplicantPositionWithApplicant(INT ID)

GetApplicantPositionWithApplicant(int id)

GetApplicantPosition(INT ID)

GetApplicantPosition(int id)

和也你的前pression(这实际上是查询逻辑,如果你仔细想想)模型(库)保持,而不是控制。

and also your expression (which are in fact query logic if you think about it) stays in model (repository) instead of controller.

编辑(回答评论)

关于通用仓库的痛:通用仓库是在一般的好主意,只有当你正在构建一些非常大的应用程序,要在更多的层,通常是分开的东西 - 数据访问层(通用库)业务层(业务逻辑,流程,先进的验证等),然后控制和presentation层(控制器+视图MVC)。在这种情况下,一般只有库封装琐碎CRUD逻辑,并只能由业务层,而不是控制器使用。

About the "pain" of generic repositories : Generic repository is in general good idea only if you are building some really BIG application, where you want to separate things in more layers, typically - data-access layer (generic repositories), business layer (business logic, workflows, advanced validation etc.), and then control and presentation layer (controller+view in MVC). In this scenario, generic repositories only encapsulate trivial CRUD logic and are used only by business layer, not controllers.

如果你没有一些沉重的东西怎么回事(非平凡的工作流程,验证需要外部服务等),那么你必须对业务层没有真正的需要,你可以在数据访问层合并它(或如果你想,合并数据访问到业务内容层,他们成为一个身体一个灵魂:)

If you dont have some heavy stuff going on (non-trivial workflows, validation requiring external services etc.), then you have no real need for business layer, and you can "merge" it in data-access layer (or if you want, merge data-access into busines layer, they become one body one soul :)

所以,如果你没有一些真正的业务层,你只能结束了在控制器的一些业务逻辑,因为你的通用信息库是不是真的适合。非通用库可以包含你的琐碎业务处理,也可以实现自定义CRUD为不同的场景 - 很好的例子是事物渴望加载,只有当你知道他们将需要)

So, if you dont have some real business layer, you can only end up with some business logic in controller, because your generic repository is not really well suited for that. Non-generic repositories can contain your trivial business processing, and also you can implement custom CRUD for different scenarios - very good example is eager loading of things only when you know they will be needed).

于是重写的决定真的是给你的,取决于你的架构和需求。

So decision of rewriting is really up to you and depends on your architecture and needs.

关于你的异常:

使用的SingleOrDefault,你的变量历史只包含一个ApplicationPositionHistory对象,你的观点预计ApplicationPositionHistory对象的枚举。在封装有明确的返回值调用库这个数据检索,你将prevent这种类型的错误。

With SingleOrDefault, your variable history contains just one ApplicationPositionHistory object, and your view expects enumeration of ApplicationPositionHistory objects. Encapsulate this data retrieval in repository call with clear return value, you will prevent this type of errors.

这篇关于asp.net mvc的页面未显示相关的,从对象的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆