Search code examples
c#linqinheritancecastingradix

Inheriting a Linq to SQL class and cast the result of a linq query


I am writing an application where we will need to extend a basic entity into a number of different things (eg employee, vehicle etc). The design is as such that there is a Entity table and a second table with type specific values eg an employee will have an ID Number but a vehicle will have a registration number.

I have inherited from the class entity generated in the Data Context but am having trouble with the casting in my repository. What is the correct way of doing this?

public class cAccountEmployee : cAccountEntity
{
    public string id_number
    {
        get
        {
            try
            {
                return this.cAccountEntityValues.Single(e => e.type == 1).value;
            }
            catch (Exception)
            {
                return "";
            }
        }

        set
        {
            try
            {
                this.cAccountEntityValues.Single(e => e.type == 1).value = value;
            }
            catch (Exception)
            {
                this.cAccountEntityValues.Add(new cAccountEntityValue()
                                            {
                                                accountentity_id = this.id,
                                                cAccountEntity = this,
                                                type = 1,
                                                value = value
                                            });
            }
        }
    }

}

Then in my repository (does not inherit anything)

public IEnumerable<cAccountEmployee> All(int accountholder_id)
    {
        return db.cAccountEntities.Where(e => e.accountholder_id == accountholder_id).OrderBy(a => a.name).Cast<cAccountEmployee>();
    }

    public cAccountEmployee Single(int id)
    {
        return db.cAccountEntities.Single(a => a.id == id) as cAccountEmployee;
    }

The cast fails in the single method and hence I get back null. It is my understanding you cannot define explicit or implicit operators from or to a base class? How can I get the base class Linq result to cast up to the inherited Employee class, while still maintaining its db state so I can submit changes?


Solution

  • With LINQ-to-SQL, there are two ways inheritance can work:

    • discriminator over a single table (not suitable since your data is not homogeneous)
    • base-class / multi-table (not that this isn't supported in the dbml - only if you write the classes manually)

    LINQ-to-SQL does not support multi-table inheritance (i.e. a single object with data from multiple tables). Entity Framework does, but is more complex; you use .Cast<T> and .OfType<T> in EF to cast/filter based on sub-types.

    You might want to look at:

    What is the purpose of the base class here? If it adds behaviour, then you can edit the dbml to specify a common base-class for all your entities. If it has data properties then it gets trickier.

    Personally, I simply wouldn't do it this way... I would keep separate classes for the different types, and use the data-context correctly, using the separate tables per type:

    public IEnumerable<Employee> All(int accountholder_id)
    {
        return db.Employees.Where(e => e.accountholder_id == accountholder_id)
            .OrderBy(a => a.name);
    }
    
    public Employee Single(int id)
    {
        return db.Employees.Single(a => a.id == id);
    }
    

    So - can you clarify what the cAccountEntity does here?