( MVC3/Entity Framework) How to perform CRUD operation in a database that uses Candidate keys as foreign keys

StackOverflow https://stackoverflow.com/questions/16301319

Domanda

I am a complete beginner in MVC3 and web development in general.

My client database uses unique candidate key of one table as foreign key of another. I cannot change the way the database is designed whatsoever. I have models derived from the database tables. I know that Entity Framework does not support candidate key as foreign key of another table.

So my question is, how do professionals work around this limitation of the entity framework?

È stato utile?

Soluzione

Since current versions of EF require FKs to point to PKs, it's not an easy problem to overcome.

One technique I've used is (with EF CodeFirst...er...Second) to override the PKEY in the Parent table's mapping and specify an anonymous type instead.

public class ParentObject
{
    public int Id {get; set;}  //the actual PKEY in the Db
    public string CandidateKey1 {get;set;}
    public string CandidateKey2 {get;set;}
    public string CandidateKey3 {get;set;}

    public virtual ICollection<ChildObject> ChildObjects {get;set;}
}

public class ChildObject
{
    public int Id {get; set;} 
    public string CandidateKey1 {get;set;}
    public string CandidateKey2 {get;set;}
    public string CandidateKey3 {get;set;}

    public virtual ParentObject ParentObject {get;set;}
}

In order for this to work, you'll need to specify that the Parent table's PKEY is an anonymous object rather than the PKEY actually stored in the DB.

public ParentObjectMap()
{
    // Primary Key
    //this.HasKey(t => t.Id); //override this as PKEY for EF purposes
    this.HasKey(t => new { t.CandidateKey1, t.CandidateKey2, t.CandidateKey3 });

    // Table & Column Mappings
    this.ToTable("ParentTable");
    this.Property(t => t.Id).HasColumnName("ParentId");
    this.Property(t => t.CandidateKey1).HasColumnName("Key1");
    this.Property(t => t.CandidateKey2).HasColumnName("Key2");
    this.Property(t => t.CandidateKey3).HasColumnName("Key3");
}

and the child object map

public ChildObjectMap()
{
    // Primary Key
    this.HasKey(t => t.Id); 

    // Table & Column Mappings
    this.ToTable("ChildTable");
    this.Property(t => t.Id).HasColumnName("ChildId");
    this.Property(t => t.CandidateKey1).HasColumnName("Key1");
    this.Property(t => t.CandidateKey2).HasColumnName("Key2");
    this.Property(t => t.CandidateKey3).HasColumnName("Key3");

    this.HasRequired(t => t.ParentObject)
        .WithMany(t => t.ChildObjects)
        .HasForeignKey(t => new { t.CandidateKey1, t.CandidateKey2, t.CandidateKey3 });
}

Of course, this introduces other problems such as uniqueueness of the actual Parent Id property which you'll need to deal with in implemented code. However, this technique has gotten the job done for me when writing code against a similar (candidate keyed) Progress 4GL OpenEdge -> MSSQL db over which I had no control.

It's also not nearly as fast as native EF -> MSSQL mappings which take advantage of FK relationships in the DB.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top