Understanding ForeignKey attribute in entity framework code first
The required side of the 1..0 relationship MemberDataSet
should not have a FK to DeferredData
. Instead, DeferredData
's PK should also be a FK to MemberDataSet
(known as shared primary key)
public class MemberDataSet
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual DeferredData DeferredData { get; set; }
}
public class DeferredData
{
// DeferredData.Id is both the PK and a FK to MemberDataSet
[Key]
[DatabaseGenerated( DatabaseGeneratedOption.None )]
[ForeignKey( "MemberDataSet" )]
public int Id { get; set; }
[Required]
public virtual MemberDataSet MemberDataSet { get; set; }
}
Fluent API:
modelBuilder.Entity<MemberDataSet>()
.HasOptional( mds => mds.DeferredData )
.WithRequired()
.WillCascadeOnDelete();
Entity Framework - Code First - Foreign Key Constraint
To add a foreign key
just add this on the Product
class add:
public int ProducerId { get; set; }
[ForeignKey("ProducerId")] //This attribute is optional bc EF should recognize Product obj specifi
public virtual Producer Producer { get; set; }
By adding public virtual Producer Producer
EF Core should recognize the ProducerId
property as a foreign key
. virtual
is used to enable Lazy Loading
if you like.
The [ForeignKey()]
is an optional attribute to explicitly point to the foreign
and navigation
keys. This post should further explain the optional use of [ForeignKey()]
.
How Should I Declare Foreign Key Relationships Using Code First Entity Framework (4.1) in MVC3?
To be clear, to simply add a foreign
key, all that is required is adding this to class:
public int ProducerId { get; set; }
public virtual Producer Producer { get; set; }
How Should I Declare Foreign Key Relationships Using Code First Entity Framework (4.1) in MVC3?
If you have an Order
class, adding a property that references another class in your model, for instance Customer
should be enough to let EF know there's a relationship in there:
public class Order
{
public int ID { get; set; }
// Some other properties
// Foreign key to customer
public virtual Customer Customer { get; set; }
}
You can always set the FK
relation explicitly:
public class Order
{
public int ID { get; set; }
// Some other properties
// Foreign key to customer
[ForeignKey("Customer")]
public string CustomerID { get; set; }
public virtual Customer Customer { get; set; }
}
The ForeignKeyAttribute
constructor takes a string as a parameter: if you place it on a foreign key property it represents the name of the associated navigation property. If you place it on the navigation property it represents the name of the associated foreign key.
What this means is, if you where to place the ForeignKeyAttribute
on the Customer
property, the attribute would take CustomerID
in the constructor:
public string CustomerID { get; set; }
[ForeignKey("CustomerID")]
public virtual Customer Customer { get; set; }
EDIT based on Latest Code
You get that error because of this line:
[ForeignKey("Parent")]
public Patient Patient { get; set; }
EF will look for a property called Parent
to use it as the Foreign Key enforcer. You can do 2 things:
1) Remove the ForeignKeyAttribute
and replace it with the RequiredAttribute
to mark the relation as required:
[Required]
public virtual Patient Patient { get; set; }
Decorating a property with the RequiredAttribute
also has a nice side effect: The relation in the database is created with ON DELETE CASCADE
.
I would also recommend making the property virtual
to enable Lazy Loading.
2) Create a property called Parent
that will serve as a Foreign Key. In that case it probably makes more sense to call it for instance ParentID
(you'll need to change the name in the ForeignKeyAttribute
as well):
public int ParentID { get; set; }
In my experience in this case though it works better to have it the other way around:
[ForeignKey("Patient")]
public int ParentID { get; set; }
public virtual Patient Patient { get; set; }
Code First entity framework and foreign keys
First change your code to this
public class Movie
{
int ID{ get; set; }
string MovieName {get; set; }
List<Actor> Actors {get; set; }
}
public class Actor
{
int ID{get;set}
string ActorName{ get; set }
Movie Movie{ get; set; }
int MovieID{ get; set; }
}
By convention EF will know that MovieID
is the foreign key to Movie
Then change Actor
code to this:
public class Actor
{
int ID{get;set}
string ActorName{ get; set; }
Movie Movies{ get; set; }
}
Actors appear in many movies. Movies have many actors.... :-)
But going back to your one-to-many where an actor only appears in one movie - if you really want the foreign key to be Move_ID
then add a data annotation:
[ForeignKey("Move_ID")]
Movie Movie{ get; set; }
Or configure it using FluentAPI
modelBuilder.Entity<Actor>()
.HasRequired(c => c.Movie)
.WithMany(d => d.Actors)
.HasForeignKey(c => c.Move_ID);
ForeignKey attribute on Entity Framework
They already are FK in your Auction
class. They will be mapped as FK. You might want to use lazy loading later on so:
public class Auction {
public int Id { get; set;}
public virtual User Seller {get; set;}
public virtual User Winner {get; set;}
}
Also you don't need the [Key]
annotation above property called Id
.
Update after question was edited:
You might need to enable migrations. Go to the Package Manager Console, if it is not open you can open it via menu View at the menu bar of the Visual Studio.
Then write in it enable-migrations
enter, then set AutomaticMigrations
in the generated class to true
, then again in Package Manager console write update-database
, run your application.
Foot notes:
You didn't state what kind of app your are creating but usually keeping user password is a bad idea. You usually suppose to keep hashed version of it.
EF6 Code first model ForeignKey
A quick guide through ForeignKey property.
When used on a key property (such as int RemoteBenchmarkId
), its name should point to the navigation property (e.g. Benchmark RemoteBenchmark
).
When used on a navigation property (this time Benchmark RemoteBenchmark
) its name should point to the key property (such as int RemoteBenchmarkId
).
The following code fragments are equivalent:
public class Context {
//...other properties
[ForeignKey("RemoteBenchmark")]
public int RemoteBenchmarkId { get; set; }
public Benchmark RemoteBenchmark { get; set; }
}
public class Context {
//...other properties
public int RemoteBenchmarkId { get; set; }
[ForeignKey("RemoteBenchmarkId")]
public Benchmark RemoteBenchmark { get; set; }
}
With that in mind, what you probably want is 4 benchmarks, each having their own foreign key column (two benchmark properties using same key would point to the same instance, which is probably not what you want), like here:
public class Context {
//...other properties
[ForeignKey("RemoteBenchmark")]
public int RemoteBenchmarkId { get; set; }
public Benchmark RemoteBenchmark { get; set; }
[ForeignKey("DataCenterBenchmark")]
public int DataCenterBenchmarkId { get; set; }
public Benchmark DataCenterBenchmark { get; set; }
[ForeignKey("IISBenchmark")]
public int IISBenchmarkId { get; set; }
public Benchmark IISBenchmark { get; set; }
[ForeignKey("LocalBenchmark")]
public int LocalBenchmarkId { get; set; }
public Benchmark LocalBenchmark { get; set; }
}
Don't forget to use [Required]
annotation if context requires specific benchmarks!
Also, you might skip the [ForeignKey]
annotations entirely allowing EF to infer columns itself (named <navigation property name>_Id
by default, such as RemoteBenchmark_Id
), but then you can't retrieve ids themselves without retrieving entire benchmark. Guess it all depends on specific cases; personally, I don't mind cluttering model with foreign key properties, since sometimes the keys themselves are enough.
(at least [ForeignKey]
annotations shouldn't be necessary; if their lack causes errors, it might be another problem entirely...?)
Cheers~!
Entity Framework Code First Foreign Key issue
It is possible set by yourself the Id of BaseCard, but first you have to use Fluent Api to specify this and the one-to-many relationship. Also, at this way, you don't have to specify attributes in your model classes. Your model classes would be like this:
public class BaseCard
{
public int Id {get ; set; }
public virtual ICollection<Skill> Skills { get; set; }
}
public class Skill
{
public int Id { get; set; }
public int BaseCardId { get; set; }
public virtual BaseCard BaseCard { get; set; }
}
As you can see, I change the navigation properties as virtual.If you define your navigation property as virtual EF will at runtime create a new class (dynamic proxy) derived from your BaseCard class and use it instead (the same happens with Skill). This new dynamically created class contains logic to load navigation property when accessed for the first time. This feature is called lazy loading.It enables Entity Framework to avoid loading an entire tree of dependent objects which are not needed from the database. You can find more info about this subject in these posts:Why Navigation Properties are virtual by default in EF and Entity Framework 4.1 Virtual Properties.
The other change that I proporse in your model is use ICollection<> type instead List<> in the Skills property. As you can see in this post, an Interface is good practice in this case. It lets you later specify the implementation that you want (could be a List<>).
Now, back to your problem,in your Context class you need to override the OnModelCreating method to specify the relationship and the no autogenerate column for Id in the BaseCards table.
public class YourContext : DbContext
{
public DbSet<BaseCard> BaseCards { get; set; }
public DbSet<Skill> Skill { get; set; }
//...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure the primary key for BaseCard
modelBuilder.Entity<BaseCard>().HasKey(t => t.Id);
//specify no autogenerate the Id Column
modelBuilder.Entity<BaseCard>().Property(b => b.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
//one-to-many relationship
modelBuilder.Entity<Skill>().HasRequired(c => c.BaseCard)
.WithMany(s => s.Skills)
.HasForeignKey(c => c.BaseCardId);
}
}
With this configuration, you have to set always the Id of BaseCard objects with a different value.
If you prefer use data annotations it is possible specify the same at this way:
public class BaseCard
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public virtual ICollection<Skill> Skills { get; set; }
}
public class Skill
{
[Key]
public int Id { get; set; }
public int BaseCardId { get; set; }
[ForeignKey("BaseCardId")]
public virtual BaseCard BaseCard { get; set; }
}
My recomendation is use Fluent API, it's more flexible and you don't have to touch your model classes. You can see some useful cosiderations in this post
Related Topics
Sqlexception:String or Binary Data Would Be Truncated
Expression-Bodied Function Members Efficiency and Performance in C# 6.0
Generate Ef Orderby Expression by String
Closing a File After File.Create
Patch Async Requests with Windows.Web.Http.Httpclient Class
How to Display the String HTML Contents into Webbrowser Control
How to Asynchronously Read the Standard Output Stream and Standard Error Stream at Once
Console App Mouse-Click X Y Coordinate Detection/Comparison
Datagridview Changing Cell Background Color
Anyone Know of a Set of C# Bindings for Ffmpeg
Variable Declarations Following If Statements
C# Linq Where Date Between 2 Dates
Linq Query Group by and Selecting First Items
Setting Dropdownlist Selecteditem Programmatically
The Data Source Does Not Support Server-Side Data Paging