简体   繁体   中英

Workaround for generics in Entity Framework

I know that generics isnt supported in EntityFramework.

For instance, this class would not be accepted or mapped:

public class Foo<T> {
   //...
}

I was wondering however if a workaround for this exists.

I have a BaseUser class:

public class BaseUser {
     [Key]
     public int Key { get; set; }

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

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

All my security logic moves around this BaseUser . It also uses some other entities such as: ApplicationClient .

ApplicationClient depends on a BaseUser entity:

public class ApplicationClient {
     //... Other properties

     [ForeignKey("User")]
     public int UserKey { get; set; }
     public virtual BaseUser User { get; set; }
}

This works fine so far.

However, a consumer of my API may extend from BaseUser and add some more properties:

public class MyUser : BaseUser {
     public string Email { get; set; }
}

This messes up everything, because ApplicationClient 's foreign key should be a reference to the MyUser table, not BaseUser .

BaseUser table should not exist, it should be replaced by a MyUser table.

So, the logical solution was this:

public class ApplicationClient<U> where U : BaseUser {
    //... Some other properties

    [ForeignKey("User")]
    public int UserKey { get; set; }
    public virtual U User { get; set; }
}

Now, when EF builds the model. The type will be resolved and it will see that a reference to MyUser is needed, and not BaseUser .

Unfortunately, EF does not support generics, and therefore throws an exception.

Is there another way to accomplish what I want to do (Or some better approach)?

I'm not very familiar with entity, as I usually prefer NHibernate, that does support inheritance mapping to a different table.

Considering EF's limitation, the best solutions I can think of are:

1- Having a User with a list of Key/Value pairs

class User {
    public int Id{get;set;}
    List<UserProperty> UserProperties {get;set;}
}

class UserProperty{
    public int Id{get;set;}
    public User User {get;set;}
    public string Key {get;set;}
    public string Value {get;set;}
}

This way your clients can add as many properties as they want. You'll have to check for duplicate keys, tough, so your UserProperty list is better kept private with the user exposing methods to access it.

2- Forget about it. If needed, your client can map your User to a one-to-one property of their user.

class User {
    public int Id{get;set;}
}

//Client Code
class ClientUser {
    public int Id{get;set;}
    public User ApiUser {get;set;}
}

Entity Framework does support all of the canonical inheritance strategies: table per class hierarchy, table per class and table per concrete class, but you will have to map the new derived class too. See an example here: http://weblogs.asp.net/ricardoperes/entity-framework-code-first-inheritance .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM