Lazy Load base types w/ EF Table Per Type?

M

Michael Bray

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?

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.)

Obviously there is a performance hit on the back-end when you actually do
access the properties of the base class due to the extra round-trip to the
data store, but it was optional, and could be specified to either perform
the lazy load or not perform the lazy load. It was under the control of
the programmer based on what he intended to do with the object.

Looking at the generated code for what I have seen so far with EF, it
doesn't seem that it doesn't support this concept, but I figured I'd take a
stab and see what this community has to say...

-mdb
 
F

Frans Bouma [C# MVP]

Michael said:
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#)
------------------------------------------------------------------------
 
M

Michael Bray

Frans Bouma said:
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.

Yes exactly! After my post I came upon this exact solution as well. I
think I could get the designer to do this if I'm careful, but I'm having
some other wierd problems with it right now (I can't move my entities
around in the design space!?!). I know I had it working with two distinct
models. The obvious problem (whether in one model or split across two) is
that you have twice the work to maintain the model(s).
Isn't that a very complex way to solve a simple projection
related
problem? :)

Probably, but it was fun to write... It turned out to be more of a
theoretical exercise for me, though, as it never saw any production use.
It actually worked quite well from a logic perspective, but I never even
got to the point of doing any performance testing, which I'm sure would
have suffered due to round trips.

-mdb
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top