Search code examples
c#inheritanceexplicit-conversion

Inheritance from Entity Framework object


I'm trying to set up retrieval from a database. I have an EF (Entity Framework) object emUser and a normal class User that inherits from emUser, but adds some extra functionality.

public class User : emUser
{
    #region Properties
    public string Username
    {
        get { return Email; }
    }
    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }
    #endregion
}

public partial class emUser : EntityObject
{
    [code ...]
}

For some reason, although User inherits from emUser I cannot explicitly convert them. The code I'm using:

List<User> returnUsers = new List<User>();
var users =
    (from u in edm.UserSet.OfType<emUser>()
    select u);

    if (users != null)
    {
        foreach (emUser user in users)
        {
            User newUser = (User)user;
            returnUsers.Add(newUser);
        }
    }
return returnUsers;

I could make User a wrapper for emUser, but then I would have to change it every time I make changes to emUser. I want to use User to differentiate between the classes used in the technical service layer and the domain layer.

I get an error message like this:

{System.InvalidCastException: Unable to cast object of type 'Services.emUser' to type 'Users.User'. at Services.DatabaseController.GetUsers() in [file path]:line 412}

Why can't I convert the emUser to a User?


Solution

  • Your problem here is what @millimoose said: EF can only return emUser objects, because it doesn't know about User and an emUser might not be a User.

    You have three possible solutions from here:

    1. Set up User to inherit from EntityObject, then have emUser inherit from User. This would be a pain to implement and not give you any useful advantages.
    2. Create Data Transfer Objects to pass around, where you basically copy all the properties from an emUser into a User (usually via the User's constructor). This would give you the separation you want, but would be a pain.
    3. Add the extra properties into a new partial class for emUser. This is the one I highly recommend, because it's simple and straightforward.

    Here's an example:

    // In a manually generated file in the same project
    public partial class emUser
    {
        #region Properties
        public string Username
        {
            get { return Email; }
        }
        public string FullName
        {
            get { return FirstName + " " + LastName; }
        }
        #endregion
    }
    
    // In the automatically generated file
    public partial class emUser : EntityObject
    {
        [code ...]
    }
    

    Usage:

    emUser foo = GetUser();
    Console.WriteLine("FirstName: " + emUser.FirstName);
    Console.WriteLine("FullName: " + emUser.FullName);