1

My code is returning the following error:

The property 'cartID' cannot be configured as a navigation property. The property must be a valid entity type and the property should have a non-abstract getter and setter. For collection properties the type must implement ICollection where T is a valid entity type.

My model is below:

[Table("ShoppingCarts")]
public class ShoppingCart 
{
    [Key]
    public string cartID { get; set; }

    public virtual ICollection<ShoppingCartItem> CartItems { get; set; }
    public DateTime? DateCreated { get; set; }
    public Guid UserID { get; set; }
}


[Table("ShoppingCartItems")]
public class ShoppingCartItem
{


    private string cartDisplayImg;

    [Key]
    [Display(Name = "Cart Item ID#")]
    public int cartItemID { get; set; }

    [Display(Name = "Cart ID")]
    [ForeignKey("cartID")]
    public string cartID { get; set; }
    [Required]
    public string itemTitle { get; set; }

    public int listingID { get; set; }
    public int sellerID { get; set; }
    [Required]
    public string sellerSKU { get; set; }
    [Required]
    public int Quantity { get; set; }
    public string itemType { get; set; }

    public string condition { get; set; }
    [Required]
    public decimal Price { get; set; }

    public string Make { get; set; }
    public string Model { get; set; }
    public string displayImgPath
    {

        get {
           cartDisplayImg = "http://www.example.com/Images/Phones/" + Make + "-" + Model + "-1.jpg";

           return cartDisplayImg;

        }

    }
    public decimal lineTotal
    {
        get {
            decimal cartLineTotal = Price * Quantity;
            return cartLineTotal; 
        }

    }

}

public class ShopingCartContext : DbContext
{

    public ShopingCartContext()
        : base("PHONEOUTLET_DBConnectionString")
    {
        Database.SetInitializer<ShopingCartContext>(new CreateDatabaseIfNotExists<ShopingCartContext>());

    }


    public DbSet<ShoppingCart> ShoppingCart { get; set; }
    public DbSet<ShoppingCartItem> ShoppingCartItems { get; set; }
}
RobIII
  • 8,488
  • 2
  • 43
  • 93
user1698144
  • 754
  • 4
  • 13
  • 36
  • I guess that is because cartID is a string? try to change it to int and add [DatabaseGenerated(DatabaseGeneratedOption.Identity)] after [Key] for auto generation. – nramirez Apr 15 '15 at 17:19

3 Answers3

6

The ForeignKey data annotation must be used on the FK property along with information telling it which navigation property represents the relationship it is a foreign key for:

[Table("ShoppingCartItems")]
public class ShoppingCartItem
{
   //..
   [Display(Name = "Cart ID")]
   [ForeignKey("Shoppingcart")]
   public string cartID { get; set; }
   public virtual ShoppingCart Shoppingcart { get; set; }
}

And alternatively, you can apply the ForeignKey annotation to the navigation property and tell it which property is the foreign key for the relationship:

[Table("ShoppingCartItems")]
public class ShoppingCartItem
{
   //..
   [Display(Name = "Cart ID")]
   public string cartID { get; set; }

   [ForeignKey("cartID")]
   public virtual ShoppingCart Shoppingcart { get; set; }
}

In addition, Code First has a set of rules that are applied to locate a foreign key property when it discovers a relationship. The conventions are based on the name of the property. The foreign key property will be discovered by convention if it is named [Target Type Key Name], [Target Type Name] + [Target Type Key Name], or [Navigation Property Name] + [Target Type Key Name]. If you use the ForeignKey data annotation these rules will be ignored because you are telling explicitly to EF what FK property you want to use.

ocuenca
  • 38,548
  • 11
  • 89
  • 102
  • I agree with this solution , although I recommend promoting EF code first conventions – IndieTech Solutions Apr 15 '15 at 17:31
  • 1
    I'm agree with you that is important to know these conventions, but I prefer to tell explicitly to EF which are my FK property using the `ForeignKey` data annotation or using Fluent Api. Anyway, I added these conventions in my answer – ocuenca Apr 15 '15 at 18:31
  • 1
    Voted up for your answer – IndieTech Solutions Apr 15 '15 at 18:32
  • The ForeignKeyAttribute on property 'cartID' on type 'MySite.Models.ShoppingCartItem' is not valid. The navigation property 'Shoppingcart' was not found on the dependent type 'MySite.Models.ShoppingCartItem'. The Name value should be a valid navigation property name. – user1698144 Apr 15 '15 at 20:35
  • Did you add the navigation property `ShoppingCart` on your `ShopingCartItem` entity?. Look the first example, I'm sure you forgot to add the `public virtual ShoppingCart Shoppingcart { get; set; }` – ocuenca Apr 15 '15 at 20:50
0

Wouldn't the type for CartID have to be an integer and not a string? I'm not sure if this would fix your issue or not, but it seems like that is what the error message is talking about.

mcloud313
  • 37
  • 6
  • That's not it. @mcloud you can create string PK using GUID() , it's easier. check out this conversation : http://stackoverflow.com/questions/1250716/why-not-always-use-guids-instead-of-integer-ids – IndieTech Solutions Apr 15 '15 at 17:24
0

Try to follow EF code conventions so instead of this

    [Display(Name = "Cart ID")]
    [ForeignKey("cartID")]
    public string cartID { get; set; } 

Try this

    [Display(Name = "Cart ID")]
    public string CartID { get; set; }
    public virtual ShoppingCart Shoppingcart { get; set; }

A common way to define one to many relationships in classes is to have a child collection in the one class and then a foreign key property along with a navigation property in the child class.


EDIT 1: Try to follow EF code conventions. Please refer to this article for more info :Code First Conventions

IndieTech Solutions
  • 2,527
  • 1
  • 21
  • 36