5

As you can see at below, there are a Lookup table for the enum values and I want to create a relationship between a table's enum values and LookupKey column of the Lookup table (instead of ID column of the Lookup table).

Lookup table:

ID   | LookupType | LookupKey | LookupValue |
101  | Status     | 0         | Passive     | 
106  | Gender     | 1         | Male        | 
113  | Status     | 1         | Active      | 
114  | Gender     | 2         | Female      | 
118  | Status     | 2         | Cancelled   | 


Main Table:

ID | Status     | Gender    | Name              | ...
1  | 0          | 1         | John Smith        | ...
2  | 1          | 2         | Christof Jahnsen  | ...
3  | 2          | 1         | Alexi Tenesis     | ...
4  | 0          | 2         | Jurgen Fechtner   | ...
5  | 1          | 2         | Andreas Folk      | ...

However, when using PK-FK relation and InverseProperty as on DataAnnotations - InverseProperty Attribute the relation is created with the ID column of the Lookup table and I cannot make the relation to the LookupKey column. Could you give an example how to achieve this?

Jack
  • 1
  • 21
  • 118
  • 236
  • 1
    Why downvote instead of an answer??? – Jack Mar 30 '15 at 06:24
  • 1
    Why don't you want to use the ID column? You can't use lookup key alone since it is not unique. I suppose you could do something tricky like .HasForeignKey(m => new {m.GenderLookupType, m.GenderLookupKey}) but now you have 2 fields in your main table for each relationship. – Steve Greene Mar 30 '15 at 14:41
  • Does it help me to make the LookupKey columns primary key besides ID column? Actually I currently use ID column for both: as "ID" and "LookupKey". However, in this situation Lookup Keys goes like 1,2,7,25, because of adding the new values in the future. On the other hand, I want the LookupKey values are created in order i.e. 1,2,3,4,.... etc. So, is it bad idea to use an extra key value i.e. "LookupKey"? What is the general usage in that situation when developers try to use a Lookup table? Do they use the ID column for both record and LookupKey? Could you please clarify me? – Jack Mar 30 '15 at 17:44

1 Answers1

3

We have a common lookup table here. It looks simlar to yours. LookupData has a primary key and a foreign key to LookupTypes which is equivalent to your enum and the value. We might also have some other simple fields like a flag or code which are identified in the LookupType metadata table. Then in out main table we might have "GenderLookupId" which points to the LookupData.Id field. The IDs themselves have no meaning and can be entered in any order. If you want gender 1 and 2 to have meaning, you should probably add another attribute for that (see surrogate keys).

Example with data:

LookupType

ID    Description    CodeDesc        BooleanDesc  
1     Genders        Gender Code     NULL
2     Races          Race Code       Is Active

LookupData

ID    LookupTypeId    Description    Code    Boolean
789   1               Male           M       NULL
790   2               White          W       True
791   1               Female         F       NULL
792   2               Hispanic       H       False

Main Name Table

NameId   Name          GenderLookupId   RaceLookupId
1234     Joe Smith     789              790
1235     Mary Meyers   791              792

Classes:

public class LookupType
{
    public int Id { get; set; }
    public string Description { get; set; }
    public string CodeDescription { get; set; }
    public string BooleanDescription { get; set; }

}

public class LookupData
{
    public int Id { get; set; }
    public int LookupTypeId { get; set; }
    public string Description { get; set; }
    public string Code { get; set; }
    public bool? BooleanValue { get; set; }
    public LookupType LookupType { get; set; } 

}

public class Name
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public int? GenderLookupId { get; set; }
    public LookupData Gender { get; set; } 
}

LookupData Config:

HasRequired(p => p.LookupType).WithMany(p=>p.LookupData).HasForeignKey(p=>p.LookupTypeId).WillCascadeOnDelete(false);

Name Config:

HasOptional(p => p.Gender).WithMany(p=>p.Name).HasForeignKey(p=>p.GenderLookupId).WillCascadeOnDelete(false);
Steve Greene
  • 12,029
  • 1
  • 33
  • 54
  • Thanks a lot for your nice explanations. As far as I see, by creating a new table with ID, LookupType and LookupKey columns my approach seems to be like this approach. So, could you please clarify me about the following approaches one by one? – Jack Mar 30 '15 at 19:11
  • 1) When converting my tables to your example I cretaed a new table to define LookupType (i.e. Gender, Status, etc) which is FK of Lookup table's TypeID. In that case I repeat codes instead of type descriptions on the Lookup table. Is that true? Is there another advantage of this? – Jack Mar 30 '15 at 19:20
  • 2) By using this approach, I will continue to use "InverseProperty" in order to use multiple FK for the same table (LookupData)? I mean that, in the Main table it is not enough to add Navigation properties referencing to the LookupData table. For example for Gender column LookupData nav property is used and for Race it will also be used. In that case a special approach should be used in order to referencing to the same table as "InverseProperty". What do you use? – Jack Mar 30 '15 at 19:27
  • 1 - It's just simple database normalization. http://www.sqlservercentral.com/blogs/abhijit_desai/2010/09/07/noramlization/ – Steve Greene Mar 30 '15 at 20:48
  • 2 - We don't put navigation collections on the child lookups - i.e.There is no collection of Names inside race or gender because we would never need to navigate in that fashion. We simply add a fluent config to Name like ...HasOptional(n => n.RaceLookup).WithMany().HasForeignKey(n => n.RaceLookupId).WillCascadeOnDelete(false); – Steve Greene Mar 30 '15 at 20:54
  • Many thanks for your reply. For the last step, could you please update your answer by simply adding the related Entity classes and the DContext containing Fluent API that indicates this "...HasOptional..." section? – Jack Mar 30 '15 at 21:59
  • Thanks a lot for your answer. I am not sure if you have voted up, but still -1 downvote :( On the other hand, as it is answer of the question I have not only vote up, but also select as answer of course :) – Jack Apr 01 '15 at 06:16