ADO.NET EF how to set FK with Code First - constraints

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

Related

Error in Entity frame work6.0.0.0:type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation

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>

Unable to retrieve metadata when controller create

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; }
}

The system cannot find the file specified " return employeeDBContext.Departments.Include("Employees").ToList();"

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........

ASP MVC4 Value was either too large or too small for an Int32 - but for a String?

this is probably glaringly obvious to experienced MVC(4) folks, so apologies in advance.
I am getting the error "Value was either too large or too small for an Int32."
The Class LEARNER has the Key LearnRefNumber which is defined as a String in the Class.
In my Model it is defined consistently as string (CSDL) and varchar2 (SSDL);XML Fragments for both of these are at the bottom of this text.
As I am passing a string and the property is defined as a string. I'm at a bit of a loss as to why I am getting this error. Is it the result of reflection by MVC? Can someone suggest a workaround?
The error appears to be occurring in the Find method of DbSet.
// My Controller ActionResult Code
public ActionResult Details(string id)
{
LEARNER learner = db.LEARNERS.Find(id);
// The above line generates an exception when I pass in the string 20044010
// as id.
if (learner == null)
{
return HttpNotFound();
}
return View(learner);
}
XML fragments from CSDL and SSDL respectively follow:
<EntityType Name="LEARNER">
<Key>
<!--<PropertyRef Name="UKPRN" />-->
<PropertyRef Name="LearnRefNumber" />
</Key>
<Property Type="String" Name="LearnRefNumber" Nullable="false" Unicode="false" FixedLength="false" MaxLength="12" />
<Property Type="Int32" Name="ULN" Nullable="false" />
<Property Type="String" Name="FamilyName" Nullable="false" Unicode="false" />
<Property Type="String" Name="GivenNames" Nullable="false" Unicode="false" />
<Property Type="DateTime" Name="DateOfBirth" Nullable="false" />
</EntityType>
<EntityType Name="LEARNER">
<Key>
<!--<PropertyRef Name="UKPRN" />-->
<PropertyRef Name="LearnRefNumber" />
</Key>
<Property Name="LearnRefNumber" Nullable="false" Type="varchar2" MaxLength="12" />
<Property Name="ULN" Type="number" Precision="10" />
<Property Name="FamilyName" Type="varchar2" MaxLength="100" />
<Property Name="GivenNames" Type="varchar2" MaxLength="100" />
<Property Name="DateOfBirth" Type="date" />
</EntityType>
LEARNER Class defintion
public partial class LEARNER
{
public LEARNER()
{
this.LEARNERCONTACTPREFERENCES = new HashSet<LEARNERCONTACTPREFERENCES>();
this.LEARNERCONTACTs = new HashSet<LEARNERCONTACT>();
this.LEARNERFAMs = new HashSet<LEARNERFAM>();
this.LLDDANDHEALTHPROBS = new HashSet<LLDDANDHEALTHPROBS>();
this.LEARNERPROVIDERSPECMONs = new HashSet<LEARNERPROVIDERSPECMON>();
this.LEARNEREMPLOYMENTSTATUS = new HashSet<LEARNEREMPLOYMENTSTATUS>();
this.LEARNINGDELIVERies = new HashSet<LEARNINGDELIVERY>();
}
public String LearnRefNumber { get; set; }
public int ULN { get; set; }
public string FamilyName { get; set; }
public string GivenNames { get; set; }
public System.DateTime DateOfBirth { get; set; }
public short Ethnicity { get; set; }
public string Sex { get; set; }
public short LLDDHealthProb { get; set; }
public string NINumber { get; set; }
public short PriorAttain { get; set; }
public short Accom { get; set; }
public int ALSCost { get; set; }
public short Dest { get; set; }
public int UKPRN { get; set; }
public int REC_ID { get; set; }
public string PrevLearnRefNumber { get; set; }
public int PrevUKPRN { get; set; }
public short PlanLearnHours { get; set; }
public short PlanEEPHours { get; set; }
public virtual ICollection<LEARNERCONTACTPREFERENCES> LEARNERCONTACTPREFERENCES { get; set; }
public virtual ICollection<LEARNERCONTACT> LEARNERCONTACTs { get; set; }
public virtual ICollection<LEARNERFAM> LEARNERFAMs { get; set; }
public virtual ICollection<LLDDANDHEALTHPROBS> LLDDANDHEALTHPROBS { get; set; }
public virtual ICollection<LEARNERPROVIDERSPECMON> LEARNERPROVIDERSPECMONs { get; set; }
public virtual ICollection<LEARNEREMPLOYMENTSTATUS> LEARNEREMPLOYMENTSTATUS { get; set; }
public virtual ICollection<LEARNINGDELIVERY> LEARNINGDELIVERies { get; set; }
}
Answer turned out (in part) to be the datatype of the ULN property (amended from Int32 to Int64).
Corrected this as suggested and things are now working the way I had hoped. Lessons learned. Thanks again for your help.
Regards,
Lee.

Why Appharbor not create all tables

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 ?

Resources