Aron Grzywaczewski
Aron Grzywaczewski

Reputation: 88

ASP.Net MVC C# model with multiple instances of another model?

I am trying to achieve system where an engineer will be able to raise a request and a person from the support will be able to assign the request to himself/herself, so that when someone will try to display the request in the website, it will appear with the name of the person who created the request and with the name of the person who the request is assigned to.

My models:

public class ConfigurationRequest
{
public virtual int     RequestId { get; set; }
public virtual int     UserId { get; set; }
public virtual int     RequestNumber { get; set; }
public virtual string  ReqDesc { get; set; }
}

public class User
{
public virtual int     UserId { get; set; }
public virtual string  UserRole {get; set; }
public virtual string  UserName {get; set; }
public virtual ICollection(ConfigurationRequest) ConfigurationReuquest { get; set; }
}

And for each configuration request I would like to display something like this in my browser:

Request Number: 2864965

Raised by (Owner): Dave Johnson

Currently Assigned to: Mike Clarke

Request Description: New points required in the fuel balancing system

Upvotes: 0

Views: 1326

Answers (1)

Steve Greene
Steve Greene

Reputation: 12304

When referencing the same class twice you will need to help entity framework figure out how to match the FKs. You can use annotations or fluent code.

public class ConfigurationRequest
{
    public int RequestId { get; set; }
    public int RequestNumber { get; set; }
    public string ReqDesc { get; set; }
    // EF will pair the below FK to nav by convention. You could also use ForeignKey attribute.
    public int RequestingUserId { get; set; }
    public User RequestingUser { get; set; }
    public int AssignedUserId { get; set; }  // make this int? if it is optional
    public User AssignedUser { get; set; }
}

public class User
{
    public int UserId { get; set; }
    public string UserRole {get; set; }
    public string UserName {get; set; }

    // you need a collection for each relationship. InverseProperty tells EF how to match them to User FK
    [InverseProperty("RequestingUser")]    
    public virtual ICollection<ConfigurationRequest> RequestsRaised { get; set; }
    [InverseProperty("AssignedUser")]    
    public virtual ICollection<ConfigurationRequest> RequestsAssigned { get; set; }
}

Or the fluent equivalent:

modelBuilder.Entity<ConfigurationRequest>()
  .HasRequired(c => c.RequestingUser)   // or HasOptional()
  .WithMany(p => p.RequestsRaised);

modelBuilder.Entity<ConfigurationRequest>()
  .HasRequired(l => l.AssignedUser)
  .WithMany(p => p.RequestsAssigned);

See here for more info. Also, don't use virtual on the non-navigation properties - those are not lazy loaded.

Now in your controller you can fetch a request, use it to fill a view model, and display the results:

context.ConfigurationRequests
       .Include(c => c.RequestingUser)
       .Include(c => c.AssignedUser)
       .FirstOrDefault(c => c.RequestId == myRequestId);

Upvotes: 1

Related Questions