i have a existing table with a primary key over 3 columns (1 varchar and 2 integer).
How can i tell the entity framework to use this "key".
Is it possible using the modelBuilder, attributes or is there another way ?
thanks!
In fluent api you must use anonymous type:
modelBuilder.Entity<YourType>()
.HasKey(e => new
{
e.VarChar,
e.Int1,
e.Int2
});
Other way is using data annotations:
public class YourType
{
[Key, Column(Order = 0)]
public string VarChar { get; set; }
[Key, Column(Order = 1)]
public int Int1 { get; set; }
[Key, Column(Order = 2)]
public int Int2 { get; set; }
}
In both scenarios order of columns is important. Once you try to use DbSet<YourType>.Find you will have to supply keys in the same order. EF also uses order internally.
Related
I'm trying to create a composite key based on three navigation properties in Entity Framework 6 : ManufacturingBundle_Id, Part_Id and Process_Id
Here is my PartProcess class I use at the moment with Id being the Primary key:
public class PartProcess
{
public int Id { get; set; }
public virtual ManufacturingBundle ManufacturingBundle { get; set; }
public virtual Part Part { get; set; }
public virtual Process Process { get; set; }
}
At the moment I get the automatically generated database table that has the following Columns:
Id | ManufacturingBundle_Id | Part_Id | Process_Id
where Id is the Primary key. I would like to get rid of the Id Column and make a composite Primary key based on ManufacturingBundle_Id, Part_Id and Process_Id
So I tried overloading the OnModelCreating method but this doesn't seem to work on typed objects, the debuggers says the properties need to be ints.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// create a composite primary key for PartProcess https://www.learnentityframeworkcore.com/configuration/fluent-api/haskey-method
modelBuilder.Entity<PartProcess>()
.HasKey(o => new { o.ManufacturingBundle, o.Part, o.Process });
base.OnModelCreating(modelBuilder);
}
How must I declare this composite primary key because I use navigation properties and the ManufacturingBundle_Id, Part_Id and Process_Id properties are autogenerated by Entity Framework?
Thanks for your help,
Ephie
Assuming ManufacturingBundle has a ManufacturingBundleId field for instance, you'd need to configure your model as follows:
public class PartProcess
{
public int ManufacturingBundleId { get; set; }
public virtual ManufacturingBundle ManufacturingBundle { get; set; }
public int PartId { get; set; }
public virtual Part Part { get; set; }
public int ProcessId { get; set; }
public virtual Process Process { get; set; }
}
Then it should let you create the composite key on the model creation, as you outlined above.
I am in a learning phase. And I want to know are foreign keys created by ASP.NET MVC-5 framework in Code First convention using entity framework nullable by default? I tried to create foreign key relationship and the foreign key column turns out to be nullable. I had a notion that if I mark a column as foreign key it should be marked as NOT NULLABLE by entity framework.
Below is the example:
One to Many: One "Standard" can have many "Children".
public class Children
{
public int Id { get; set; }
public string Name { get; set; }
public int StandardId { get; set; }
[ForeignKey("StandardId")]
public virtual Standard Standard { get; set; }
}
public class Standard
{
public Standard()
{
Children = new List<Children>();
}
public int Id { get; set; }
public string StandardName { get; set; }
public virtual ICollection<Children> Children { get; set; }
}
With just above configuration, the Foreign Key "StandardId" is coming out to be Nullable in database. I just want to know is this expected behaviour? Are foreign keys are suppose to be NULLABLE by DEFAULT or I have not wired up foreign key property properly?
You must tell EF explicitly, that you want this field to be not nullable:
public class YourContext : DbContext
{
public DbSet<Children> Childrens { get; set; }
public DbSet<Standard> Standards { get; set; }
protected override void OnModelCreating(DbModelBuilder dBModelBuilder)
{
modelBuilder.Entity<Children>().HasRequired(x => x.Standard);
}
}
I am using code first in asp mvc and i came across a situation where i need to have a model/table with a computed primary key for example:
public class Student
{
[Key]
public string StudentNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime RegistrationDate { get; set; }
}
So is there a way to make the StudentNumber to be computed by for example taking 1st letter of the LastName, the year of registration and an autoincrement number?
For performance reasons, you really don't want to have your primary key as a string, so question where this requirement is coming from. However:
[Key]
public int Id { get; set; }
[NotMapped]
public string StudentId
{
get
{
return string.Format("{0}{1}{2}",
this.LastName.Substring(0, 1),
this.RegistrationDate.Year,
this.Id);
}
}
I am trying to figure out how to make MVC Scaffolding to work with composite/complex key.
I have the following table:
public class Data
{
[Key, Column(Order = 0)]
[ForeignKey("Note")]
[Display(Name = "Note id")]
public int NoteId { get; set; }
[Key, Column(Order = 1)]
[ForeignKey("Member")]
[Display(Name = "Member id")]
public int MemberId { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
[Display(Name = "Note")]
public virtual Note Note { get; set; }
[Display(Name = "Member")]
public virtual Member Member { get; set; }
}
When I execute the line for scaffolding:
Scaffold Controller Data -Repository
I receive the following error:
Get-PrimaryKey : Cannot find primary key property for type
Pro.Web.Models.Data'. Multiple properties appear to be
primary keys: NoteId, MemberId
What could be the solution for this problem? I use Visual Studio 2012.
Thanks.
The class PrimaryKeyLocation under the T4Scaffolding.Core.PrimaryKeyLocators namespace has a list of IPrimaryKeyLocator interfaces that are implemented on the PrimaryKeyLocation.cs file itself.
Reading the five implementations available, one can tell that your code will fall on the KeyAttributePropertyLocator implementation returning both members marked with the [Key] attriubute, but the GetPrimaryKeyCmdlet.cs that is run from the T4 engine and that calls the PrimaryKeyLocation class has the following implementation:
switch (primaryKeyProperties.Count)
{
case 0:
// Code when no key is found
case 1:
// Code when one key is found
default:
// Code when more than one key is found
WriteError(string.Format("Cannot find primary key property for type '{0}'.
Multiple properties appear to be primary keys: {1}",
foundClass.FullName, primaryKeyPropertyNames));
}
Therefore, as the switch statement does not deal with more than one key, composite keys are not supported. One way out of this is to implement the case for composite keys, but I would not know the implications of that on the t4 templates themselves.
Source code for the scaffolding tool.
This question already has answers here:
EntityType has no key defined error
(13 answers)
Closed 6 years ago.
Developing a basic ASP.net MVC 4 application. Its a simple product catalog application, where in I have 2 database tables ('Category' and 'Products')
There is a foreign key reference of 'Category id' (primary key in Category table) in 'Products' table.
When I run the application, I am getting error message (listed below).
System.Data.Entity.Edm.EdmEntityType: : EntityType 'Category' has no key defined. Define the key for this EntityType.
System.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'Category' is based on type 'Category' that has no keys defined
This looks like a common error for newbies,I did check all the related solutions to 'Entity key '' has no key defined.' but still my problem is not solved, Kindly help me in understanding this problem and what is the correct solution to this problem.
Below are my model classes
Category.cs
namespace ChemicalStore.Models
{
public partial class Category
{
public int CatId { get; set; }
public string CatName { get; set; }
public string CatDescription { get; set; }
public List<Product> Product { get; set; }
}
}
Products.cs
namespace ChemicalStore.Models
{
public class Product
{
public int ProductId { get; set; }
public int CatId { get; set; }
public string ProductTitle { get; set; }
public string ProductPrice { get; set; }
public string ProductDescription { get; set; }
public string ProductPackage { get; set; }
}
}
You should add attribute [Key] before property CatId:
using System.ComponentModel.DataAnnotations;
public partial class Category
{
[Key]
public int CatId { get; set; }
public string CatName { get; set; }
public string CatDescription { get; set; }
public List<Product> Product { get; set; }
}
The problem is that EF can work only when it knows primary key of table. By default EF recognize as primary key property with name Id. If your table has another primary key, you can mark it with attribute [Key] or set Key with fluent configuration.
Entity Framework uses a primary key field to create the primary key column on the generated table.
It uses convention to get this column with some variations:
If the field is called id or any casing variance;
If the field is called ClassNameId of any casing variance;
I may be missing some more conventions, but these are the most common cases.
If you don't have any field with this conventions you need to mark your desired primary key with the attribute [Key]:
[Key]
public int CatId { get; set; }
I was able to solve this by adding a setter to my key property; I only had a getter before.
public int Id { get; set; }
Just place [key] attribute on above id ..
[Table("employee")]
public class Employee
{
[Key]
public int Empno { set; get; }
public string Empname { set; get; }
}
Entity classes are auto generated..
Manual changes to those files will be overwritten if the code is regenerated.
You need to create a partial class with all your metadata
[MetadataType(typeof(Category.CategoryMetadata))]
public partial class Category
{
internal sealed class CategoryMetadata
{
[Key]
public int CatId { get; set; }
[Required]
public string CatName { get; set; }
public string CatDescription { get; set; }
public List<Product> Product { get; set; }
}
}
Read more on MSDN
Hi if you are getting below error.
""One or more validation errors were detected during model generation:
Checking.Models.Employee: : EntityType 'Employee' has no key defined. Define the key for this EntityType.""
just check your table column name and defined property name same or not .
if not then correct it proble resolved.
In my case I fixed this problem adding the right connectionString in the web.config/app.config file.
I had forgotten adding it and the DBContext was not able to communicate with the DB.
Hope it helps