I am relatively new to the first Code for Entity Framework approach. I have long used the Database First approach, but Code First seems to be better suited for the application I'm currently developing. I work with an existing MS SQL database and I am not allowed to make any changes to the database. The reason I use Code First is because the Fluent API allows me to dynamically assign a table name to a class.
However, I have a predicament when I need to assign a relationship between two tables. One table, ArCodes, has a composite key consisting of CodeType and Code (both are rows). The CodeType column identifies the code type, and the Code column is an identifier unique to the code type.
public class ArCode { [Column("cod_typ", Order = 0), Key] public string CodeType { get; set; } [Column("ar_cod", Order = 1), Key] public string Code { get; set; } [Column("desc")] public string Description { get; set; } }
The other Invoice table should refer to the ArCodes table for ship through code and terms.
public class Invoice { [Column("pi_hist_hdr_invc_no"), Key] public int InvoiceNumber { get; set; } [Column("shp_via_cod")] public string ShipViaCode { get; set; } public ArCode ShipVia { get; set; } [Column("terms_cod")] public string TermsCode { get; set; } public ArCode Terms { get; set; } }
I would like to establish relationships for both the ShipVia property and the Conditions property. However, I'm not sure how to do this in relation to the CodeType part of the composite key. For βshipβ codes, the code type must be βSβ and the code βtermsβ with codes, the code type must be βTβ.
I tried using DB Context, but this did not work:
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
Any help would be appreciated.
Update # 1
Well, I reduced my code to its simplest form, and I executed the solution provided by @GertArnold.
public abstract class ArCode { [Column("cod_typ")] public string CodeType { get; set; } [Column("ar_cod")] public string Code { get; set; } [Column("terms_desc")] public string TermsDescription { get; set; } [Column("terms_typ")] public string TermsType { get; set; } [Column("shp_via_desc")] public string ShipViaDescription { get; set; } [Column("tax_desc")] public string TaxDescription { get; set; } } public class TermsCode : ArCode { } public class ShipViaCode : ArCode { } public class Invoice { [Column("pi_hist_hdr_invc_no"), Key] public int InvoiceNumber { get; set; } [Column("hdr_invc_dat")] public DateTime InvoiceDate { get; set; } [Column("shp_via_cod")] public string ShipViaCode { get; set; } public ShipViaCode ShipVia { get; set; } [Column("terms_cod")] public string TermsCode { get; set; } public TermsCode Terms { get; set; } public Invoice() { } } public class PbsContext : DbContext { public DbSet<Invoice> Invoices { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Invoice>().ToTable("IHSHDR"); modelBuilder.Entity<ArCode>().HasKey(r => r.Code).ToTable("ARCODS"); modelBuilder.Entity<TermsCode>().Map(m => m.Requires("CodeType") .HasValue("T").HasColumnType("varchar").HasMaxLength(1).IsRequired()) .ToTable("ARCODS"); modelBuilder.Entity<ShipViaCode>().Map(m => m.Requires("CodeType") .HasValue("S").HasColumnType("varchar").HasMaxLength(1).IsRequired()) .ToTable("ARCODS"); base.OnModelCreating(modelBuilder); } public PbsContext() : base("name=PbsDatabase") { } }
However, the following code returns an error:
PbsContext context = new PbsContext(); var invoice = context.Invoices.OrderByDescending(r => r.InvoiceDate).FirstOrDefault();
error 3032: a problem with displaying fragments starting from line 28: a condition member "ArCode.cod_typ" with a condition other than "IsNull = False" is displayed. Either remove the condition on ArCode.cod_typ, or remove it from the mapping.
If I remove the "CodeType" column from the ArCode class and change all the "CodeType" links to the database column name "cod_typ" in the OnModelCreating event, then the above expression is executed without errors. However, invoice.ShipVia and invoice.Terms will be null, although there is a corresponding entry in the database.
Update # 2
public abstract class ArCode { [Column("ar_cod")] public string Code { get; set; } [Column("terms_desc")] public string TermsDescription { get; set; } [Column("terms_typ")] public string TermsType { get; set; } [Column("shp_via_desc")] public string ShipViaDescription { get; set; } [Column("tax_desc")] public string TaxDescription { get; set; } } public class TermsCode : ArCode { } public class ShipViaCode : ArCode { } public class Invoice { [Column("pi_hist_hdr_invc_no"), Key] public int InvoiceNumber { get; set; } [Column("hdr_invc_dat")] public DateTime InvoiceDate { get; set; } [Column("shp_via_cod")] public ShipViaCode ShipVia { get; set; } [Column("terms_cod")] public TermsCode Terms { get; set; } public Invoice() { } } public class PbsContext : DbContext { public DbSet<Invoice> Invoices { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Invoice>().ToTable("IHSHDR"); modelBuilder.Entity<ArCode>().HasKey(r => r.Code).ToTable("ARCODS"); modelBuilder.Entity<TermsCode>().Map(m => m.Requires("CodeType") .HasValue("T").HasColumnType("varchar").HasMaxLength(1).IsRequired()) .ToTable("ARCODS"); modelBuilder.Entity<ShipViaCode>().Map(m => m.Requires("CodeType") .HasValue("S").HasColumnType("varchar").HasMaxLength(1).IsRequired()) .ToTable("ARCODS"); base.OnModelCreating(modelBuilder); } public PbsContext() : base("name=PbsDatabase") { } }
Now the following code returns an error:
PbsContext context = new PbsContext(); var invoice = context.Invoices.OrderByDescending(r => r.InvoiceDate).FirstOrDefault();
EntityCommandExecutionException - Invalid column name 'ShipVia_Code'. Invalid column name 'Terms_Code'.