Caverman
Caverman

Reputation: 3739

Entity Framework navigation property not working?

I'm still learning EF and I'm trying to learn how to use a ViewModel and JOIN with multiple tables. Researching I think I found how to do it but it's not working.

I have two tables, CustomerCall and CallStatus. The customer call has a Status (int) field and the CallStatus will have the display name of the status. So I need to JOIN those together.

In my research it looks like I need a Navagation property in my ViewModel and then use the .Include of EF. So, I created a FK in SQL between CustomerCall.Status and CallStatus.Id.

Here are my class and View Model

[Table("CustomerCall")]
public partial class CustomerCall
{
    public int Id { get; set; }

    [StringLength(50)]
    public string CustomerName { get; set; }

    [StringLength(50)]
    public string Subject { get; set; }

    [Column(TypeName = "text")]
    public string Comment { get; set; }

    public DateTime? CallDate { get; set; }

    public int? Status { get; set; }

    public int? AssignedTo { get; set; }

    public DateTime? CreateDate { get; set; }
}

public partial class CallStatus
{
    public int Id { get; set; }

    [StringLength(25)]
    public string StatusName { get; set; }
}

public class CustomerCallVM
{
    public int Id { get; set; }

    [DisplayName("Customer Name")]
    public string CustomerName { get; set; }

    public string Subject { get; set; }

    public string Comment { get; set; }

    [DisplayName("Call Date")]
    public DateTime? CallDate { get; set; }

    public int? Status { get; set; }

    [DisplayName("Status")]
    public string StatusName { get; set; }

    public int? AssignedTo { get; set; }

    [DisplayName("Assigned To")]
    public string AssignedToName { get; set; }

    [DisplayName("Create Date")]
    public DateTime? CreateDate { get; set; }


    public CallStatus CallStatus { get; set; }

}

Here is the EF in my repository I'm trying to use but I get an error "A specified Include path is not valid. The EntityType 'CPPCustomerCall.ViewModels.CustomerCall' does not declare a navigation property with the name 'CallStatus'"

public CustomerCallVM SelectById(int? id)
{
    using (DataContext db = new DataContext())
    {
        db.Configuration.AutoDetectChangesEnabled = false;      //no changes needed so turn off for performance.

        CustomerCallVM customerCall = new CustomerCallVM();

        var call = db.CustomerCalls.Include("CallStatus").Where(c => c.Id == id).FirstOrDefault();


        return customerCall;
    }
}

Upvotes: 0

Views: 443

Answers (2)

Matt Rowland
Matt Rowland

Reputation: 4595

The error you are receiving is telling you that you need a navigation property. The .Include() is eager loading. This loading needs to load the entity into something. That something is the navigation property.

The code below is what your CustomerCall class needs to look like with the addition of the Navigation Property.

[Table("CustomerCall")]
public partial class CustomerCall
{
    public int Id { get; set; }

    [StringLength(50)]
    public string CustomerName { get; set; }

    [StringLength(50)]
    public string Subject { get; set; }

    [Column(TypeName = "text")]
    public string Comment { get; set; }

    public DateTime? CallDate { get; set; }

    public int? Status { get; set; }

    public int? AssignedTo { get; set; }

    public DateTime? CreateDate { get; set; }

    //This is your navigation property
    [ForeignKey("Status")]
    public virtual CallStatus CallStatus { get; set; }
}

Upvotes: 0

CodeCaster
CodeCaster

Reputation: 151720

I need a Navagation property in my ViewModel

No, that won't work. Entity Framework doesn't know anything about your viewmodel, and also doesn't know about the relation between CustomerCall and CallStatus. You need that navigation property in your entity model CustomerCall.

You also need a CallStatusVM.

Then you can query your database:

var customerCall = db.CustomerCalls.Include(c => c.CallStatus).Where(...).FirstOrDefault();

And then you can map it to your viewmodel:

var customerCallVM = new CustomerCallVM
{
    Id = customerCall.Id,
    CustomerName = customerCall.CustomerName,
    // ...
    CallStatus = new CallStatusVM
    {
        Id = customerCall.CallStatus.Id,
        StatusName = customerCall.CallStatus.StatusName,
    }
};

The latter can be made easier with AutoMapper.

Upvotes: 2

Related Questions