Entity Framework [ForeignKey]

0

Reading a tutorial on the entity framework, I came across a rather strange example for me. This example is about the DataAnnotation [ForeignKey]

public class Student
{
    public Student()
    { 

    }
    public int StudentID { get; set; }
    public string StudentName { get; set; }

    //Foreign key for Standard
    public int StandardId { get; set; }

    public Standard Standard { get; set; }
}

public class Standard
{
    public Standard()
    { 

    }
    public int StandardId { get; set; }
    public string StandardName { get; set; }

    public ICollection<Student> Students { get; set; }

    }

In a non-ORM scenario, that is, dealing directly with ADO.net, I see no sense that Student has an attribute referring to Id of Standard , since Student already has a reference to Standard , where this reference already has Id . Why does EF work in this way? It seems redundant to me.

    
asked by anonymous 05.05.2016 / 17:38

3 answers

2

Matheus, I believe you are not taking into account one thing: LazyLoad .

Defined to LazyLoad, when searching for a Student , only Student data is retrieved from the Bank, only if you come to access the Standard Browsing property that EF will fetch your data. / p>

To do this lazy loading, it is necessary that the navigation property has the virtual modifier, so EF can modify its behavior.

Note the mapping of your entities using Code First , you might notice this better.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;

public partial class Contexto : DbContext
{
    public Contexto() : base("name=Contexto")
    {
    }

    public virtual DbSet<Standard> Standards { get; set; }
    public virtual DbSet<Student> Students { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Standard>().Property(e => e.Name).IsUnicode(false);
        modelBuilder.Entity<Standard>().HasMany(e => e.Students).WithRequired(e => e.Standard).WillCascadeOnDelete(false);
        modelBuilder.Entity<Student>().Property(e => e.Name).IsUnicode(false);
    }
}

[Table("Student")]
public partial class Student
{
    public int StudentID { get; set; }

    [Required]
    [StringLength(50)]
    public string Name { get; set; }

    public int StandardID { get; set; }

    public virtual Standard Standard { get; set; }
}

[Table("Standard")]
public partial class Standard
{
    public Standard()
    {
        Students = new HashSet<Student>();
    }

    public int StandardID { get; set; }

    [Required]
    [StringLength(50)]
    public string Name { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

If you create a new Student entity, and set a value to StandardID that already exists in the database, and after trying to access the Standard property, EF fetches the data from the% in the Database.

But if you do not access the navigation property and only set the Standard property value, the additional query will not be performed, but if you try to save the StandardID entity, EF will have no problem doing so.

Note that it is not always necessary to access a navigation property, sometimes knowing only the ID of the property is enough.

    
05.05.2016 / 18:11
2

As said in the comments by @Bigown , it is difficult to judge whether it is correct or not the mapping without the context, what can be done is to analyze and explain what the code is doing.

This mapping is not wrong:

public class Student
{
    public Student()
    { 

    }
    public int StudentID { get; set; }
    public string StudentName { get; set; }

    //Não necessida da anotação [ForeignKey]
    public int StandardId { get; set; }

    public Standard Standard { get; set; }
}

public class Standard
{
    public Standard()
    { 

    }
    public int StandardId { get; set; }
    public string StandardName { get; set; }

    public ICollection<Student> Students { get; set; }

    }

In the code above, we have a 1: N mapping, where Standard has several Students , where StandardId property is foreing key of the Student template. That's right, if that's the goal. Using the Entity Framework, it is not necessary to use the [ForeignKey] annotation, since the name of the foreing key is the name of the navigation property with the prefix id , that is, StandardId (Standard + Id). >

In contrast, the Standard has a collection of Students , where it does not need to have a foreing key for Students , characterizing the connection of 1 : N .

    
05.05.2016 / 18:08
-1

It's very simple. The Entity Framework will, in any case, create this StandardId in the database. What happens is, do you want to control the creation of this column or not?

Another, you can query the Student table without going to the Standard table. Example: You need to select all Student of Standard 10 .

_context.Students
    .Where(student => student.StandardId == 10)
    .ToList(); // Acessa apenas a entidade Student
// SELECT * FROM Student WHERE StandardId = 10

If you leave implicit the StandardId , you would have to do:

_contexto.Students
    .Where(student => student.Standard.Id == 10)
    .ToList(); // Acessa entidades Student e Standard
// SELECT Student.* FROM Student
//   JOIN Standard ON Standard.Id = Student.StandardId
//  WHERE Standard.Id = 10
    
05.05.2016 / 18:53