Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Entity Inheritance #5813

Closed
danielcirket opened this issue Jun 20, 2016 · 11 comments
Closed

Question: Entity Inheritance #5813

danielcirket opened this issue Jun 20, 2016 · 11 comments

Comments

@danielcirket
Copy link

danielcirket commented Jun 20, 2016

Steps to reproduce

public class User : Entity { //... }
public class UserViewModel : User, INotifyPropertyChanged {  //...  }

public DataContext : DbContext
{
  public DbSet<User> Users { get; set; }
  //...
}

public UserService : IDataService<User>
{
  public int? Update(User user) 
  {
    _dataContext.Users.Update(user);
    _dataContext.SaveChanges();
    //...
  }
  //...
}

var user = _userService.GetById(1);
var userViewModel = new UserViewModel(user);
_userService.Update(userViewModel);

The issue

Exception message: The entity type 'UserViewModel' was not found. Ensure that the entity type has been added to the model.

Can't use a subtype to save an instance of base type, can/how should this be configured, is it possible?

Further technical details

EF Core version: 1.0.0-rc2-final
Operating system: Windows 10
Visual Studio version: VS 2015 Pro

@ajcvickers
Copy link
Member

@danielcirket Do you want UserViewModel to be mapped to the database? In other words, if you save a UserViewModel to the database and then later query it back, do you want it to come back as a UserViewModel object or as a User object?

@danielcirket
Copy link
Author

danielcirket commented Jun 20, 2016

@ajcvickers, thank you for the prompt response.

Just the user object mapped to the database, and to get a user object back rather than a UserViewModel.

The Get/List are currently along these lines:

User GetUserByName(string name);
User GetUserById(int id);
IEnumerable<User> Query(Expression<Func<User, bool> >predicate);

@Bartmax
Copy link

Bartmax commented Jun 24, 2016

Looks like a bug to me. EF seems to be looking to the underlying object type.

@ajcvickers
Copy link
Member

@Bartmax It's not really a bug, it's something that is currently not supported. It would be easy to support it, but there are usability implications in doing so that we will discuss in triage before making a decision.

@Bartmax
Copy link

Bartmax commented Jun 24, 2016

Ok good to know then.

@danielcirket
Copy link
Author

Yeah I'd agree with @ajcvickers, it's not really a bug, it's how the internals work (There's a lot of stuff that happens for mapping types etc), it's just missing functionality unfortunately.

You could get around this problem by having an extra layer between the data access and the front end business layer which would handle the object type translations (Things like automapper make this easier), but that just adds another layer of complexity which may not necessarily be wanted based on product/size/scale etc.

@rowanmiller
Copy link
Contributor

At this stage this isn't a feature we are planning to enable. In general it seems having a View Model inherit from a Model type isn't really a common practice. Typically it would wrap the type rather than inherit.

We are willing to reconsider if we see more folks want this feature.

@Bartmax
Copy link

Bartmax commented Jun 24, 2016

Actually having the viewmodel inherit from the model introduce overposting vulnerability

@soycabanillas
Copy link

soycabanillas commented Jul 5, 2016

I tried to use inheritance to have different representations of the same data using a text/JSON field (oversimplified version):

public class Person
{
    [Key]
    public long Id { get; set; }

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

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

public class Customer : Person
{
    public class CustomerData
    {
        public string VipLevel { get; set; }
        public string Preferences { get; set; }
    }

    [NotMapped]
    public CustomerData Data
    {
        get { return JsonConvert.DeserializeObject<CustomerData>(Serialized); }
        set { Serialized = JsonConvert.SerializeObject(value); }
    }
}

public class Employee : Person
{
    public class EmployeeData
    {
        public string Name { get; set; }
        public decimal Salary { get; set; }
    }

    [NotMapped]
    public EmployeeData Data
    {
        get { return JsonConvert.DeserializeObject<EmployeeData>(Serialized); }
        set { Serialized = JsonConvert.SerializeObject(value); }
    }
}

When the exception
Ensure that the entity type has been added to the model.
hit me, I tried to use TPH, but then the "Discriminator" field appeared. That forced me to use a new DbSet (and a new repository) for every child and what is worse, I couldn't search for the parent entity anymore.

What if I need to query for any person, customer or employee, with a given name?

@rowanmiller
Copy link
Contributor

@soycabanillas this issue is closed and your scenario appears to be unrelated to the issue being discussed here. Can you open a new issue.

@soycabanillas
Copy link

Done! #6001

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants