How to create Multiple one-to-one relationships in EF Code first?

asp.net-mvc c# ef-code-first entity-framework entity-framework-6

Question

Third Edit: Changed plenty of my code at the end of the question, left the original just in case that was the way to go.

I'm having a problem understanding how to work with multiple one-to-one relationships in EF. I already had made a one-to-one relationship between two models, but when I tried to add another model one-to-one relationship to the mix, things got ugly. Second Edit: I now am working with Composite keys, since there are another relationships in the database that seemed to use them. Still having problems doing the one-to-one relationships, here's the code:

First, I got the one of the parents:

public class CodigoAgrupadorCuentas
{
   [Key]
    [Column(Order = 0)]
    [StringLength(36)]
    public string CompanyID { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(36)]
    public string DivisionID { get; set; }

    [Key]
    [Column(Order = 2)]
    [StringLength(36)]
    public string DepartmentID { get; set; }

    [Key]
    [Column(Order = 3)]
    [Required]
    public int CodigoAgrupadorCuentasID { get; set; }

    [Required]
    public string Code { get; set; }

    public virtual CatalogoDeCuentas CatalogoDeCuentas { get; set; }
}

Here's the the child that has two parents:

public class CatalogoDeCuentas 
{
    public CatalogoDeCuentas()
    { }
     [Key]
    [Column(Order = 0)]
    [StringLength(36)]
    public string CompanyID { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(36)]
    public string DivisionID { get; set; }

    [Key]
    [Column(Order = 2)]
    [StringLength(36)]
    public string DepartmentID { get; set; }

    [Key]
    [Column(Order = 3)]
    [Required]
    public int CatalogoDeCuentasID { get; set; }

    public string Information { get; set; }

    public virtual CodigoAgrupadorCuentas CodigoAgrupadorCuentas { get; set; }

    public virtual LedgerChartOfAccount LedgerChartOfAccount { get; set; } 

}
}

Second Parent class:

public partial class LedgerChartOfAccount
{
    [Key]
    [Column(Order = 0)]
    [StringLength(36)]
    public string CompanyID { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(36)]
    public string DivisionID { get; set; }

    [Key]
    [Column(Order = 2)]
    [StringLength(36)]
    public string DepartmentID { get; set; }

    [Key]
    [Column(Order = 3)]
    [StringLength(36)]
    public string GLAccountNumber { get; set; }

    public string description { get; set; }


    public virtual CatalogoDeCuentas CatalogoDeCuentas { get; set; }
}

And finally, here's the context:

public class PolizasDBContext: DbContext
{
      public PolizasDBContext()
        : base("PolizasDBContext")
    { 

    }

      public DbSet<CatalogoDeCuentas> TablaCatalogoDeCuentas { get; set; }
      public DbSet<CodigoAgrupadorCuentas> TablaCodigoAgrupCuentas { get; set; }
      public DbSet<LedgerChartOfAccount> TablaChartAccounts { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
       modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<LedgerChartOfAccount>()
          .HasKey(x => new { x.CompanyID, x.DivisionID, x.DepartmentID, x.GLAccountNumber });

        modelBuilder.Entity<CatalogoDeCuentas>()
            .HasKey(x => new { x.CatalogoDeCuentasID, x.CompanyID, x.DivisionID, x.DepartmentID });

        modelBuilder.Entity<CodigoAgrupadorCuentas>()
            .HasKey(x => new { x.CodigoAgrupadorCuentasID, x.CompanyID, x.DivisionID, x.DepartmentID });

        modelBuilder.Entity<CatalogoDeCuentas>()
            .HasRequired(x => x.CodigoAgrupadorCuentas)
            .WithOptional(x => x.CatalogoDeCuentas)
            .Map( x => x.MapKey("CompanyID"));

        modelBuilder.Entity<CatalogoDeCuentas>()
           .HasRequired(x => x.LedgerChartOfAccounts)
           .WithOptional(x => x.CatalogoDeCuentas)
           .Map(x => x.MapKey("CompanyID"));

        base.OnModelCreating(modelBuilder);

    }

At this point, I get the next error when I try to scaffold:

Scaffolding Error

In Summary: What would be the way, to keep a one to one relationship between CodigoAgrupadorCuentas and CatalogoDeCuentas, and at the same time have a one to one relationship between LedgerChartOfAccount and Catalogo de Cuentas?

First Edit: Forgot to mention, that GLAccountnumber was suppose to be LedgerChartOfAccounts Key.

Third Edit:

Still trying to fix this, and I honestly have no idea why i'm struggling so much, from all the research I have done it should be simple. I have made again plenty of changes to the code above. Here's the changes:

 public class CodigoAgrupadorCuentas
{
    [Key]
    [Required]
    public int CodigoAgrupadorCuentasID { get; set; }

    [Required]
    public string Code { get; set; }

    public CatalogoDeCuentas CatalogoDeCuentas { get; set; }
}

Removed the Composite keys from Codigo Agrupador, since from what I read, I don't necessarily need them to make this work. Also removed the virtual keyword virtual from CatalogoDeCuentas, because of an error I had that i'll show at the end. But anyways, I also changed:

public class CatalogoDeCuentas 
{
    public CatalogoDeCuentas()
    { }

    [Key]
    [Column(Order = 0)]
    [Required]
    public int CatalogoDeCuentasID { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(36)]
    [Required]
    public string GLAccountNumber { get; set; }

    public string Information { get; set; }

    public CodigoAgrupadorCuentas CodigoAgrupadorCuentas { get; set; }

    public LedgerChartOfAccount LedgerChartOfAccount { get; set; } 

}
}

Almost same changes, only that in this case, I wanted to link CatalogoDeCuentas and LedgerAccountOfChart with the GLAccountNumber, that's why I added it as a key.

Another big change was on the Context:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        modelBuilder.Entity<CatalogoDeCuentas>()
            .HasRequired(x => x.CodigoAgrupadorCuentas)
            .WithOptional(x => x.CatalogoDeCuentas);

        modelBuilder.Entity<CatalogoDeCuentas>()
           .HasRequired(x => x.LedgerChartOfAccounts)
           .WithOptional(x => x.CatalogoDeCuentas);

        base.OnModelCreating(modelBuilder);

    }

Made it a lot simpler. The only change I did to LedgerChartOfAccounts from the original code posted was removing the virtual word in CatalogoDeCuentas.

Now, when I try to scaffold, I get the next error:

New Scaffold Error

And that's where I am so far... help?

1
1
10/1/2014 4:19:04 PM

Popular Answer

For it to be (One-to-One) LedgerChartOfAccount should have a primary key of public int CatalogoDeCuentasID {get; set;}

In the model builder your configuration should look like this:

modelBuilder.Entity<LedgerChartOfAccount>()
                   .HasKey(x => x.CatalogoDeCuentasID);

modelBuilder.Entity<LedgerChartOfAccount>()
            .HasRequiredPrincipal(x => x.CatalogoDeCuentas)
            .WithRequired(x => x.LedgerChartOfAccount);

For more information check out Configuring Relationships with the Fluent API

0
9/29/2014 11:20:18 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow