I'm trying to create controller with vies for entity framework. As model class I'm going to use Product class:
public class Product
{
public int ProductId { get; set; }
public int CategoryId { get; set; }
public int ManufacturerId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string PhotoUrl { get; set; }
public Category Category { get; set; }
public Manufacturer Manufacturer { get; set; }
}
And like data context class this:
public class RetroGadgetEntities:DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
The problem is that I get an error when trying to create controller "Unable to retrieve metadata for 'RetroGadget.Models.Product'". As I understand it is actualy thrown when code generator trying to create strongly typed view, but I can't figure out why.
UPD: Here is my Web.config.
<connectionStrings>
<add name="RetroGadgetCon" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=RetroGadget.Models.RetroGadgetEntities;Integrated Security=True;" providerName="System.Data.SqlClient"/>
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
UPD2
public class Product
{
[Key]
public int ProductId { get; set; }
public int CategoryId { get; set; }
public int ManufacturerId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string PhotoUrl { get; set; }
[ForeignKey("CategoryId")]
public Category Category { get; set; }
[ForeignKey("ManufacturerId")]
public Manufacturer Manufacturer { get; set; }
}
Why this error thrown and what I can do with it?
Ok, I'v solved it. The actual problem was with linked classes.
public class Category
{
[Key]
public int CategoryId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Product> Products { get; set; }
}
public class Manufacturer
{
[Key]
public int ManufacturerId { get; set; }
public string Name { get; set; }
}
Problem was that there was no field Products in Manufacturer class. So I'v changed this like this.
public class Manufacturer
{
[Key]
public int ManufacturerId { get; set; }
public string Name { get; set; }
public List<Product> Products { get; set; }
}
Here are possible fixes you can do:
1) If you're using Code First & error message indicates Entity 'X' has no key defined or EntitySet 'X' is based on type 'Y' that has no keys defined, add primary key attribute (KeyAttribute
) to model class property which serves as identity column:
using System.ComponentModel.DataAnnotations;
public class Product
{
[Key] // add this attribute
public int ProductId { get; set; }
// other properties
}
Additionally, ensure that DbContext
constructor contains reference to named connection string in web.config:
public class RetroGadgetEntities : DbContext
{
public RetroGadgetEntities() : base("RetroGadgetCon")
{
}
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
Afterwards, ensure all foreign keys & table relationships are arranged well (add ForeignKeyAttribute
& ICollection
if required).
2) If error message indicates Unrecognized element 'providers', this provider
section in web.config possibly causing metadata problem on EF context when creating controller from a model (often occurs when you're downgrading default EF version used by template to previous one):
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
Try removing that provider
part so that the entityFramework
section becomes this:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
NB: The connection string section seems used invalid database location namespace as RetroGadget.Models.RetroGadgetEntities
, try changing Initial Catalog
to use a database name instead:
<add name="RetroGadgetCon" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=(database name);Integrated Security=True;" providerName="System.Data.SqlClient"/>
If the connection still not working with given LocalDB instance, add AttachDbFilename="(database path)\(database name).mdf"
& use Data Source=(LocalDb)\v11.0
(depending on LocalDB version, see SQL Server connection string).
References:
Cannot create controller with Entity framework - Unable to retrieve metadata for ' '
Entity Framework: Unrecognized element 'providers' exception