Question

Issue with ASP .NET 4 MVC, Entity Framework 4.4 Relatively inexperienced on above, so sorry if the issue is obvious, but it has me stumped and google foo is not working.

Using Code first to create DB (using Devart MySQL dot net connector) Getting exception

*System.InvalidOperationException: The foreign key component 'Clinician_ClientId' is not a declared property on type 'Clinician_Client'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

Things were running smoothly until I tried to implement a joining table with payload. Aim: a client can have many clinicians and a clinician can have many clients, with payload been the start/end periods.

Code below with just to essentials

  /// <summary>
/// Represents a clinician of the system
/// </summary>
public class Clinician
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int clinicianId { get; set; }


    [ForeignKey("UserDetails")]
    public int UserDetailsId { get; set; }
    public virtual UserDetails UserDetails { get; set; }

    [ForeignKey("Clinician_Client")]
    public int Clinician_ClientId { get; set; }
    public virtual ICollection<Clinician_Client> Clinician_Client { get; set; }
}

client class

/// <summary>
/// Represents a client of the system
/// </summary>
public class Client
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int clientId { get; set; }

    //Snip other fields

    [ForeignKey("UserDetails")]
    public int UserDetailsId { get; set; }
    public virtual UserDetails UserDetails { get; set; }

    [ForeignKey("Clinician_Client")]
    public int Clinician_ClientId { get; set; }
    public virtual ICollection<Clinician_Client> Clinician_Client { get; set; }


}

joining table

/// <summary>
/// Represents a clinicians care period over a client
/// </summary>
public class Clinician_Client
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Clinician_ClientId { get; set; }

    public DateTime start_dttm { get; set; }
    public DateTime end_dttm { get; set; }

    //foreign keys
//    [ForeignKey("Client")]
    public int ClientId { get; set; }
//    public virtual Client Client { get; set; }

//    [ForeignKey("Clinician")]
    public int ClinicianId { get; set; }
//    public virtual Clinician Clinician { get; set; }
}

context

  public class UsersContext : DbContext
{
    public UsersContext()
        : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<UserDetails> UserDetails { get; set; }
    public DbSet<Client> Client { get; set; }
    public DbSet<Clinician> Clinician { get; set; }
    public DbSet<Clinician_Client> Clinician_Client { get; set; }
}

Have tried playing with nullable (the join is optional), the foreign keys on the join table, to no avail. Problem is I don't understand the error, the field is apart of the class and the model.

Was it helpful?

Solution

Here's your problem:-

[ForeignKey("Clinician_Client")]
public int Clinician_ClientId { get; set; }
public virtual ICollection<Clinician_Client> Clinician_Client { get; set; }

What do you suppose the value of Clinician_ClientId should be?

It can't be the Clinician_ClientId of the related Clinician_Client object, because you intend each Clinician (and each Client) to be associated with many Clinician_Client objects.

It looks like the model builder is looking at the type ICollection<Clinician_Client> for a property to match with Clinician_ClientId (e.g. "Id"). It doesn't have one, because it's an ICollection<Clinician_Client>, not a Clinician_Client.

As an aside, you might want to consider giving your Clinician_Client object a better name to describe its payload. Perhaps "CarePeriod"?

Try something more like the following:-

public class Clinician
{
  public int ClinicianId { get; set; }

  public virtual ICollection<CarePeriod> CarePeriods { get; set; }

  ...
}

public class Client
{
  public int ClientId { get; set; }

  public virtual ICollection<CarePeriod> CarePeriods { get; set }

  ...
}

public class CarePeriod
{
  public int CarePeriodId { get; set; }

  public int ClinicianId { get; set; }
  public virtual Clinician Clinician { get; set; }

  public int ClientId { get; set; }
  public virtual Client Client { get; set; }

  ...
}

You shouldn't need to mess around with [Key] attributes, etc. The default conventions should have you covered, unless I'm missing something about your connector.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top