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?
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
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; }
}
Related
I have a grid view and object data source on webpage.Below are the classes created for code first approach.
public class Department
{
public int deptId{ get; set; }
public string deptName { get; set; }
public string location { get; set; }
public List<Employee>Employees { get; set; }
//CodeFirstExample.Employee edf = new Employee();
}
public class Employee
{
public int empId { get; set; }
public string empName { get; set; }
public int salary { get; set; }
public Department Department { get; set; }
}
public class EmployeeDBContext:DbContext
{
public DbSet<Department> Departments{ get; set; }
public DbSet <List<Employee>> Employees { get; set; }
}
public class EmployeeRepository
{
public List<Department> GetDepartments()
{
EmployeeDBContext emp = new EmployeeDBContext();
return emp.Departments.ToList();
}
}
in web.config file connection string as fllowed
<connectionStrings>
<add name="EmployeeDBContext"
connectionString="data source=.\SQLSERVER;initial catalog=Sample; integrated security=SSPI"
providerName="System.Data.SqlClient"/>
</connectionStrings>
I am developing web application using vs 2017 ,EF v 6.0.1 with code first approach.On running the application I am getting error at employee repository class, return statement as "The system cannot find the file specified. return employeeDBContext.Departments.Include("Employees").ToList();".I am unable to upload the picture to explain clearly. And also I am using gridview with object datasource.
The below is my code along with connection strings.So, please Let me know where the problem is...
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public int Salary { get; set; }
public Department Department { get; set; }
}
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public List<Employee> Employees { get; set; }
}
public class EmployeeDBContext:DbContext
{
public DbSet<Department> Departments { get; set; }
public DbSet<Employee> Employees { get; set; }
}
public class EmployeeRepository
{
public List<Department> GetDepartments()
{
EmployeeDBContext employeeDBContext = new EmployeeDBContext();
return employeeDBContext.Departments.Include("Employees").ToList();
}
}
<connectionStrings>
<add name="EmployeeDBContext" providerName="System.Data.SqlClient"
connectionString="server=.;uid=sa;pwd=P#ssw0rd;database=Sample;" />
The system cannot find the file specified "return employeeDBContext.Departments.ToList(); "
The mistake is at web.config connectionstring. I replaced the following code
<connectionStrings>
with the code
<connectionStrings>
<add name="EmployeeDBContext" providerName="System.Data.SqlClient" connectionString="server=.\SQLSERVERR2;uid=sa;pwd=P#ssw0rd;database=Sample;" />
Changed the server name.
Thanks........
I am trying to retrieve data as XML using Entity Framework and WebAPI.
All I get is an empty Child container, I have populated two records in OrderItem with OrderId=1 yet still nothing, see <OrderItems/> below:
<ArrayOfOrder xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebApplication6.Models">
<Order>
<ID>1</ID>
<OrderItems/>
<Username>Test</Username>
</Order>
</ArrayOfOrder>
My Order model is as follows:
public class Order
{
public Order()
{
this.OrderItems = new HashSet<OrderItem>();
}
public int Id { get; set; }
public string Username { get; set; }
public ICollection<OrderItem> OrderItems { get; set; }
}
My OrderItems model is as follows:
public class OrderItem
{
public int Id { get; set; }
public int OrderId { get; set; }
public int Qty { get; set; }
public Order Order { get; set; }
}
Controller code for GetOrders:
// GET api/Order
public IQueryable<Order> GetOrders()
{
return db.Orders;
}
I am just trying to learn entity framework and WebApi, this part seems to be basic functionality and I can't find any solid reference to this at a basic level. Can anyone explain what I am missing?
After hours of searching I found the solution. Basically I needed to include the sub-dataset. This is done in the controller function:
public IQueryable<Order> GetOrders()
{
return db.Orders.Include(p => p.OrderItems);
}
However this introduces the error:
Object graph for type
'System.Collections.Generic.HashSet`1[[WebApplication7.Models.OrderItem,
WebApplication7, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]]' contains cycles and cannot be serialized if
reference tracking is disabled.
Which is fixed for XML by using Datacontracts
Updated OrderItem model:
using System.Runtime.Serialization;
[DataContract]
public class OrderItem
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int OrderId { get; set; }
[DataMember]
public int Qty { get; set; }
public Order Order { get; set; }
}
Note there is no [DataMember] annotation before Order
Now my result is as expected:
<ArrayOfOrder xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebApplication7.Models">
<Order>
<Id>1</Id>
<OrderItems>
<OrderItem>
<Id>2</Id>
<OrderId>1</OrderId>
<Qty>231</Qty>
</OrderItem>
<OrderItem>
<Id>4</Id>
<OrderId>1</OrderId>
<Qty>2314</Qty>
</OrderItem>
</OrderItems>
<Username>first</Username>
</Order>
</ArrayOfOrder>
Why Appharbor not create all tables.
I have the following Entity Framework Configuration.
public class RezaWebContext : DbContext
{
public RezaWebContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<RegistrantInfo> RegistrantInfos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<RegistrantInfo>().HasRequired(x => x.UserProfile).WithOptional(x => x.RegistrantInfo);
}
}
public class RegistrantInfo
{
public virtual int RegistrantInfoId { get; set; }
public virtual string Name { get; set; }
public virtual string Sex { get; set; }
public virtual string BirthPlace { get; set; }
public virtual string BirthDate { get; set; }
public virtual string Address { get; set; }
public virtual string ExamNumber { get; set; }
public virtual UserProfile UserProfile { get; set; }
}
//this tables used by ASP.Net Simple Membership
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual RegistrantInfo RegistrantInfo { get; set; }
}
connString :
<add name="DefaultConnection" connectionString="server=localhost\SqlExpress; database=RezaWeb;
user id=sa; password=123456; MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
in my computer. All database tables created.
RegistrationInfo + SimpleMembership tables (UserProfile, webpages_Membership, webpages_OAuthMembership, webpages_Roles, webpages_UsersInRoles)
in appharbor : all SimpleMembership tables created but "RegistrationInfo" table not created.
Why ?
I have these classes that describes my DB model:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public string DisplayName { get; set; }
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
}
It's working fine, but when I try to add FK constraint in App.Config like this:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value="System.Data.SqlClient" />
</parameters>
</defaultConnectionFactory>
<Association Name="UserBlogs">
<End Type="CodeFirstNewDatabaseSample.BloggingContext.User" Role="User" Multiplicity="1" >
<OnDelete Action="Cascade" />
</End>
<End Type="CodeFirstNewDatabaseSample.BloggingContext.Blog" Role="Blog" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="User">
<PropertyRef Name="UserId" />
</Principal>
<Dependent Role="Blog">
<PropertyRef Name="UserId" />
</Dependent>
</ReferentialConstraint>
</Association>
</entityFramework>
I get an error that App.Config has threw an error. How can I add FKeys using this code as a sample and is App.Config the right place to do that?
The modelbuilder is my preferred method of configuring FKs with Entity Framework
Check out my blog post which goes into the details of how to do this here: http://blog.staticvoid.co.nz/2012/7/17/entity_framework-navigation_property_basics_with_code_first