EF6 code first relationship between entities

I'm trying to create a condo data model in ASP.NET with SQL Server. I ran into the creation of the relationship of proprietario(1) with fracao(many).

The Error returned is:

The INSERT statement conflicted with the FOREIGN KEY constraint " FK_dbo.Fracao_dbo.Owner_propertyoid". The conflict occurred in database "WebCond", table " dbo.Owner", column 'ProprietarioID'.

My classes:

[Table("Fracao")]
public class Fracao
{


    [ScaffoldColumn(false)]
    public int FracaoID { get; set; }

    public int? ProprietarioID { get; set; }
    public virtual Proprietario Proprietario { get; set; }

    [Required]
    public int CondominioID { get; set; }
    public virtual Condominio Condominio { get; set; }

    [Required]
    public int ZonaID { get; set; }
    public virtual Zona Zona { get; set; }

    [Required, StringLength(4), Display(Name = "Letra")]
    public string Letra { get; set; }

    [Required, Display(Name = "Área")]
    public decimal Area { get; set; }

    [Required, Display(Name = "Permilagem")]
    public decimal Permilagem { get; set; }

    [Required, StringLength(4), Display(Name = "Piso")]
    public string Piso { get; set; }

    [Required, StringLength(10), Display(Name = "Porta")]
    public string Porta { get; set; }

}

[Table("Proprietario")]
public class Proprietario
{

    [ScaffoldColumn(false)]
    public int ProprietarioID { get; set; }

    [Required, StringLength(255), Display(Name = "Nome")]
    public string Nome { get; set; }

    [Required, StringLength(500), Display(Name = "Morada"), DataType(DataType.MultilineText)]
    public string Morada { get; set; }

    [Required, StringLength(30), Display(Name = "CPostal")]
    public string CPostal { get; set; }

    [Required, StringLength(100), Display(Name = "Localidade")]
    public string Localidade { get; set; }

    [StringLength(10), Display(Name = "Telefone")]
    public string Telefone { get; set; }

    [StringLength(10), Display(Name = "Telemovel")]
    public string Telemovel { get; set; }

    [DataType(DataType.EmailAddress), Display(Name = "Email")]
    public string Email { get; set; }

    [StringLength(10), Display(Name = "Contribuinte")]
    public string Contribuinte { get; set; }

    public virtual ICollection<Fracao> Fracoes { get; set; }
}

I tried to create the entities in the way I created others that are fine, but these are not.

It seems to me that the problem is related to cascade delete, and that I have to create the appropriate exceptions, but I don't know which ones.

Author: Alexandre Marcondes, 2014-01-31

2 answers

You could try with the following, code:

[Table("Fracao")]
    public class Fracao
    {


        [ScaffoldColumn(false)]
        public int FracaoID { get; set; }

        public int? ProprietarioID { get; set; }

        [InverseProperty("ID")]
        [ForeignKey("ProprietarioID")]
        public virtual Proprietario Proprietario { get; set; }

        [Required]
        public int CondominioID { get; set; }
        public virtual Condominio Condominio { get; set; }

        [Required]
        public int ZonaID { get; set; }
        public virtual Zona Zona { get; set; }

        [Required, StringLength(4), Display(Name = "Letra")]
        public string Letra { get; set; }

        [Required, Display(Name = "Área")]
        public decimal Area { get; set; }

        [Required, Display(Name = "Permilagem")]
        public decimal Permilagem { get; set; }

        [Required, StringLength(4), Display(Name = "Piso")]
        public string Piso { get; set; }

        [Required, StringLength(10), Display(Name = "Porta")]
        public string Porta { get; set; }

    }

Because with [ForeignKey("ProprietarioID")], you tell the annotation that FK is the one defined within it.

Update

Errata, I did not pay attention to the fact that your identifier has the same name as the foreign key, so please remove the annotation [InverseProperty("ID")].

Update 2

With the following code, which I replicated entirely on my machine, worked perfectly, try to do the same, as a test, as a new project:

DbContext class:

public class TesteContext : DbContext
{
    public DbSet<Fracao> Fracoes { get; set; }
    public DbSet<Proprietario> Proprietarios { get; set; }
}

Fraction Class:

[Table("Fracao")]
public class Fracao
{
    [ScaffoldColumn(false)]
    public int FracaoID { get; set; }

    public int? ProprietarioID { get; set; }

    [ForeignKey("ProprietarioID")]
    public virtual Proprietario Proprietario { get; set; }

    [StringLength(4), Display(Name = "Letra")]
    public string Letra { get; set; }

    [Display(Name = "Área")]
    public decimal Area { get; set; }

    [Display(Name = "Permilagem")]
    public decimal Permilagem { get; set; }

    [StringLength(4), Display(Name = "Piso")]
    public string Piso { get; set; }

    [StringLength(10), Display(Name = "Porta")]
    public string Porta { get; set; }

}

Owner Class:

[Table("Proprietario")]
public class Proprietario
{
    [ScaffoldColumn(false)]
    public int ProprietarioID { get; set; }

    [StringLength(255), Display(Name = "Nome")]
    public string Nome { get; set; }

    [StringLength(500), Display(Name = "Morada"), DataType(DataType.MultilineText)]
    public string Morada { get; set; }

    [StringLength(30), Display(Name = "CPostal")]
    public string CPostal { get; set; }

    [StringLength(100), Display(Name = "Localidade")]
    public string Localidade { get; set; }

    [StringLength(10), Display(Name = "Telefone")]
    public string Telefone { get; set; }

    [StringLength(10), Display(Name = "Telemovel")]
    public string Telemovel { get; set; }

    [DataType(DataType.EmailAddress), Display(Name = "Email")]
    public string Email { get; set; }

    [StringLength(10), Display(Name = "Contribuinte")]
    public string Contribuinte { get; set; }

    public virtual ICollection<Fracao> Fracoes { get; set; }
}

And the codes of a console program:

using (var db = new TesteContext())
{
    // Create and save a new Blog 
    Console.Write("Enter a name for a new Blog: ");
    var name = Console.ReadLine();

    var proprietario = new Proprietario { Email = "oi" };
    proprietario = db.Proprietarios.Add(proprietario);
    db.SaveChanges();

    var fracao = new Fracao { Area = 1, Proprietario = proprietario };
    db.Fracoes.Add(fracao);
    db.SaveChanges();

    // Display all Blogs from the database 
    var query = from b in db.Fracoes
                orderby b.Area
                select b;

    Console.WriteLine("All blogs in the database:");
    foreach (var item in query)
    {
         Console.WriteLine(item.Area);
    }

    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

With this code, you can enter a fraction and an owner, doing the binding correctly, if you want to do the update, you will have to do the following:

var fracao = new Fracao { Area = 1, Proprietario = null, ProprietarioId = proprietario.ProprietarioId };

Try again with these codes and comment if you achieve.

 1
Author: BetaSystems - Rodrigo Duarte, 2014-02-01 00:43:27

In class Proprietario, put a constructor that initializes ICollection<Fracoes>. For example:

public class Proprietario {

   public Proprietario( ) {
      Fracoes = new List<Fracao>( );
   }

   ...

   public virtual ICollection<Fracao> Fracoes { get; set; }

}

Thus correctly configures the One-To-Many relationship between the models. There is an article here in English that explains as well.

Update

I created my own Code-first and copied their classes the way they are, with my modification (I didn't include Zona or Condominio only). In the end, I had a class like this:

Fracao

[Table( "Fracao" )]
public class Fracao
{
    [ScaffoldColumn( false )]
    public int FracaoID { get; set; }

    public int? ProprietarioID { get; set; }
    public virtual Proprietario Proprietario { get; set; }

    [Required, StringLength( 4 ), Display( Name = "Letra" )]
    public string Letra { get; set; }

    [Required, Display( Name = "Área" )]
    public decimal Area { get; set; }

    [Required, Display( Name = "Permilagem" )]
    public decimal Permilagem { get; set; }

    [Required, StringLength( 4 ), Display( Name = "Piso" )]
    public string Piso { get; set; }

    [Required, StringLength( 10 ), Display( Name = "Porta" )]
    public string Porta { get; set; }
}

owner

[Table( "Proprietario" )]
public class Proprietario
{
    public Proprietario( )
    {
        Fracoes = new List<Fracao>( );
    }

    [ScaffoldColumn( false )]
    public int ProprietarioID { get; set; }

    [Required, StringLength( 255 ), Display( Name = "Nome" )]
    public string Nome { get; set; }

    [Required, StringLength( 500 ), Display( Name = "Morada" ), DataType( DataType.MultilineText )]
    public string Morada { get; set; }

    [Required, StringLength( 30 ), Display( Name = "CPostal" )]
    public string CPostal { get; set; }

    [Required, StringLength( 100 ), Display( Name = "Localidade" )]
    public string Localidade { get; set; }

    [StringLength( 10 ), Display( Name = "Telefone" )]
    public string Telefone { get; set; }

    [StringLength( 10 ), Display( Name = "Telemovel" )]
    public string Telemovel { get; set; }

    [DataType( DataType.EmailAddress ), Display( Name = "Email" )]
    public string Email { get; set; }

    [StringLength( 10 ), Display( Name = "Contribuinte" )]
    public string Contribuinte { get; set; }

    public virtual ICollection<Fracao> Fracoes { get; set; }
}

And I ended up with tables and columns like this:

example of tables and columns generated by Entity Framework 6 Code-First

 2
Author: brazilianldsjaguar, 2014-02-03 17:53:59