Michael Bray wrote:
With the recent release of EF I've decided to dig into it a bit more than I
did before... the question I'm specifically interested in, but haven't
been able to find a resource to answer it is... when using Table-per-Type
with inherited entities, is it possible to lazy load the base classes?
For example, if I have an entity called "Person" and an entity called
"Employee" and (obviously) Employee inherits from Person, is it possible to
have EF only load the properties associated w/ Employee, and not perform
the join to the Person table until necessary?
No O/R mapper which does its job properly would allow that, directly,
as in: load an entity and fetch only the derived entity's fields. This
is because the derived entity's fields are ALSO the fields from Person,
so in general: Employee's fields are Person's fields + the fields only
defined in Employee.
THe thing is that a field defined in Employee, e.g. BadgeNo, has no
meaning outside the context of its associated Person fields.
So even though you could for example define a query like:
var q = from e in ctx.Employee
select new Employee() { BadgeNo=e.BadgeNo,
/* other fields only defined in Employee */ };
It makes no sense not to join with person even though there aren't any
person fields involved.
The above query already gives you a possibility of how to solve it with
an O/R mapper which allows multiple entities mapped onto the same table
(e.g. our LLBLGen Pro does that). You map a second Employee Entity onto
the Employee table, but this time, you dont make it a subtype of person.
Then your query becomes:
var q = from e in ctx.EmployeeNotSubtype
select new Employee() { BadgeNo=e.BadgeNo,
/* other fields only defined in Employee */ };
where EmployeeNotSubtype is the second mapped entity. Not sure if EF
supports this, I do recall it doesn't do this in the designer, but I'm
not sure, so you've to check.
Inheritance in the db isn't something which is free. THis is often
overlooked by POCO oriented developers who think that their class
hierarchies can be persisted without worries into databases using
relational schemas which have no clue what inheritance is.
As Nijssen/Halpin described in their NIAM books: flattening inheritance
hierarchies can be done in a couple of ways, but all have their side
effects and disadvantages. One therefore should choose the hierarchy
based on the nature of the data that's expected, which is against some
OO design principles perhaps, but so be it: in practise, applications
simply have to do what they're suppose to so if they're dogslow because
some OO guru thought it would be great to have deep inheritance
hierarchies with big queries as a result... that's not the way to go ;)
Obviously this would result in an object that was only half-loaded. A year
or two back, I wrote my own ORM that actually did this - it worked by
dynamically building a new proxy object that derived from the type desired
(using Emit) and overriding the properties of the base class (which had to
be declared virtual), so that when the user requested a property on the
base class, it went back to the database to retrieve those properties. (As
an aside, the really neat thing about this was that it worked even when
inspecting the properties via the VS Debugger - that is, viewing the object
in the debugger, it always appeared as if the entire object was loaded - it
was possible but quite difficult to actually see the object in an unloaded
state.)
Isn't that a very complex way to solve a simple projection related
problem? :)
FB
--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website:
http://www.llblgen.com
My .NET blog:
http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------