Archive

Posts Tagged ‘Entity Framework’

Entity Framework, IronPython and PODO’s – Can it be done? - Part 3

January 13th, 2010 Simon Segal 1 comment

Before we dive into proxies when using POCO in the Entity Framework lets have a quick recap on where we left off in part 2.0.

  • Entity Framework will load PODO’s (plain old DLR Objects) fine as long as:
    • No primitives other than strings are used for fields and properties
  • Eager Loading works when ObjectQuery[T].Include() is used.
    • TSQL profiling confirms this.
  • Lazy Loading does not appear to work at all
  • Type names of materialized entities are not what are expected for runtime generated proxies.

Let’s talk about proxies a little. I wont delve too deep only enough that’s relevant to the problem at hand. Entity Framework creates proxies at runtime for our POCO entities, essentially so the framework can know the entities a vice versa, they maintain the glue so to speak. The glue is there to enable lazy loading and change tracking specifically. If you want to know more about proxies I suggest reading this post from the ADO.Net team blog. Figure 1.0 depicts debug data of a materialized proxy Entity in a C# library. Notice the unusual name of the proxy Entity in the watch window in figure 1.0 – the Entity Framework generates proxy types in the System.Data.Entity.DynamicProxies namespace.

Figure 1.0

podos_part3_proxy_vs2010

At this point, we know we are not seeing proxy type names come back when we ask our PODO for it’s full name and we are not getting any love from Lazy Loading at all. Our materialized Entities are indeed the type as engineered via __clrtype__ and we saw this when querying for the namespace of the Entity from IronPython in part 2.0.

In a nutshell, the Entity Framework is querying the database and materializing our PODO’s, however given the circumstances its reasonable to argue that no proxying is taking place and hence no lazy loading. Let’s put that theory to the test just a little more shall we! When proxies are employed in the Entity Framework there are two basic usages; proxies that support either Lazy Loading only or Change Tracking with Lazy Loading, the latter option requires all mapped properties be declared virtual and be public or protected. In Python class properties, functions and methods are considered to be as good as virtual, so we will just assume for the moment that this clears the way for the Entity Framework to work with our PODO’s as any other normal compliant class that is proxyable (of course there is no such word).

Since we are getting no proxy generation with our PODO’s then we would equally expect change tracking to fail would we not? Note in figure 1.0 that a (C#) proxy when examined has a reference to the Entity Tracker and other Entity Framework plumbing required to manage it, which we would expect to be missing if our theory about what’s happening to our PODO’s is correct. Let’s now put the whole proxy and change tracking question to rest.

def IsProxy(theType):
    ctxType = ObjectContext.GetObjectType(theType.GetType())
    notNull = theType != None
    isCtxObj = ctxType != theType.GetType();
    print \tThis entity is a %(podo)s \
                %{podo:theType.GetType()}
    print \tIt’s type in the ObjectContext is %(ctxType)s \
                %{ctxType:ctxType}
    return notNull and isCtxObj

def IsChangeTracking(podo):
    state = ctx.ObjectStateManager.GetObjectStateEntry(podo).State
    print \tIt’s state is: %(state)s % {state:state}
    return state == System.Data.EntityState.Modified

ctx.ProxyCreationEnabled  = True

parents = ctx.ParentRecords\
             .Where(it.ParentID != ‘bob’)\
             .Include(ChildRecords)

for parent in parents:
    print parent.ParentID
    parent.ParentName = change tracking works nonetheless
    isProxy = IsProxy(parent).ToString()
    isChange = IsChangeTracking(parent).ToString()
    print \tIt is %(proxy)s that this PODO is a proxy \
                %{proxy:isProxy}
    print \tIt is %(change)s that this PODO supports  \
                proxy style change tracking %{change:isChange}
    if parent.ChildRecords != None:
        for child in parent.ChildRecords:
            print \t\tChildID is :  + child.ChildID

ctx.SaveChanges()

We have added two methods, one to check if an Entity is a proxy and another to verify if change tracking is working via our proxy. Running this code produces the following TSQL, subsequent changes to the database and debug window output in NetBeans.

exec sp_executesql N‘update [dbo].[ParentRecords]
set [ParentName] = @0
where ([ParentID] = @1)
‘,N‘@0 nvarchar(50),@1 char(5)’,@0=N‘change tracking’,@1=‘FGHIJ’

podos_part3_change_track_ok

image

An interesting set of results. As suspected we have no proxies with Lazy Loading or Change tracking ability but we do have change tracking nonetheless when we get a diff from the ObjectContext. The call to .SaveChanges() on the ObjectContext is still persisting the change to the database regardless of the absence of the proxy creation.

To summarise, we now have established that loading data into PODO’s works despite producing no proxy. We can eager load only and we still have the rather large problem with natives that are not strings; this still leaves us with the little problem of this ugly message.

image

One thing that I meant to mention in one of the earlier posts is that clrtype.py does not support the use of iterables and IronPython classes in the @Accepts and @Returns decorators out of the box. Thanks to help given by Lukas Cenovsky on the IronPython mailing list who made the required changes to the validate_clr_types method in clrtype.py to get over this hurdle.

So now it’s time I thought to jump into VS 2010 and see what we can discover by checking out the dump file created by the IPY.exe crash. And that is where part 4.0 of the series will start. Until then.

Share/Save/Bookmark

Entity Framework – Repositories, Fetching Strategies, Specification and Mapping – Using NFetchSpec for Role Driven Development. Parts 1 - 4

January 11th, 2010 Simon Segal 2 comments

Over the course of the next month or so I will be posting a series on using a set of helper libraries which I refer to as NFetchSpec. I have taken the somewhat unusual course of creating this dedicated post that will act as an index of sorts for this series. Another reason for this aggregated index page is that the title of the series accurately reflects the intent of its content however not so much in a search friendly way and I want to make sure that it can be easily found by people who are interested in using Repositories, Fetching Strategies, Specifications and code only mapping.

NFetchSpec aims to provide a basis for using Repositories, Fetching Strategies, Specifications and Code Only mapping using a Role Driven methodology. Here is some example consumer code of NFetchSpec:

Listing 1.0

var customersStartWithA =
    new Specification<IMakeCustomerPrefered>
        (c => c.CompanyName.StartsWith(”A”));

var fetch = new FetchingStrategy<IMakeCustomerPrefered>(true);

fetch.AddIntentions(new IEagerFetchingIntention[]
{
    EagerFetchingIntention.CreateInstance<IMakeCustomerPrefered,
                                          ICollection<IOrder>>(c => c.Orders)
});

var repo = new CustomerBuyingStatusRepository();

var custs =
    repo.Get<IMakeCustomerPrefered>(customersStartWithA, fetch);

foreach (var cust in custs)
{
    cust.MakePrefered();
}

As described in Part 1.0, a role is an interface that describes a business or system event and can flag our  intention; in the case of the code above, the intention is to make the Customer Preferred. Using NFetchSpec, this style of working (using roles) seeps into all aspects of the code. This is certainly not a requirement to use NFetchSpec and I will give some examples to the contrary as we get deeper into the series of posts, but it is the key reason for developing it. In Listing 1.0 we are using NFetchSpec to create a search predicate using a Specification instance, a Fetching Strategy to determine the most appropriate loading for the role and then finally using the Repository to get a Customer to make preferred. The API of NFetchSpec supports writing code like this, where each of the moving parts can be written in line together, however as mentioned in Part 1.0, one of the benefits of working in this role driven way is that we can use some IoC techniques to discover the correct Specifications and Fetching Strategies based on their implementing a given role, i.e, the interface that is specified to the Repositories .Get<TRole>() method. This is closer to the intended proposed usage:

Listing 2.0

var repo = new CustomerBuyingStatusRepository();

var custs =
    repo.Get<IMakeCustomerPrefered>();

The Code here in Listing 2.0 will instruct the NFetchSpec infrastructure to find a fetching strategy and Specification for this role when the overloaded version of the .Get<TRole>() method is called. This approach makes for an extremely flexible approach, swapping out the most appropriate component – if I don’t like the fetching strategy for a given role, I can simply replace it, facilitating just in time performance tuning (in the case of fetching) as we observe the system over time.

Here are the links to the posts in the series. You might notice that some of the links are not complete meaning that that post is yet to come. I will update this list as new posts make there way out.

Helping the Entity Framework Play it’s <Role> Part 1.0 (posted)

Helping the Entity Framework Play it’s <Role> Part 2.0 (posted)

Helping the Entity Framework Play it’s <Role> Part 3.0 (posted)

Helping the Entity Framework Play it’s <Role> Part 4.0 (posted)

All the code will be available on conclusion with the final post. Just one small thing before signing off, I really want to re-emphasise that it’s a really good idea to watch Udi present the ideas that lead me to attempt accommodating this approach for Entity Framework.

Share/Save/Bookmark

Entity Framework, IronPython and PODO’s – Can it be done? - Part 2

January 7th, 2010 Simon Segal No comments

Part 1.0 was setting up for the idea and now in part 2.0 we start to flesh out all the moving parts that would be required to work with IronPython and the Entity Framework and furthermore, do so in such a way that is parallel to how we expect to do so in a statically typed language such as C#. What we are going to aim for is POCO classes, a custom Object Context and Code Only mapping.

Before we move on a small piece of housekeeping. When you see [T] in this post it is the IronPython version of <T> in the C# world. For example these are equivalent:

ObjectQuery<T>

//and

ObjectQuery[T]

PODO / POCO Entities

I gave a bit of a sneak peak at this in Part 1.0 but it’s worth repeating here. Using Northwind (of course – it’s law after all) we could start building out our business Entities for Customers and Orders. Let’s start by keeping the members of our entities to a minimum for brevity sake:

Figure 1.0

simple model 

Simple enough, a couple of classes with members types that include System.String, System.DateTime and System.Int32, a list of Orders in the Customer Entity and a single entity reference to Customer from the Order Entity. I posted a Customer Entity in part 1.0 but let’s list both Customer and Order here:

Listing 1.0

import clrtype
import clr
from System import *
from System.Collections.Generic import *
from Entities2.Order import Order

class Customer(object):

    __metaclass__ = clrtype.ClrClass
    _clrnamespace = EntityFramework.Podo
    _clrfields = {  _customerId:str,
                    _companyName:str,
                    _contactName:str,
                    _orders:clr.GetClrType(ICollection)
                    .MakeGenericType(Order)
                 }

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(str))
    def CustomerID(self):
        return self._customerId

    @CustomerID.setter
    @clrtype.accepts(clr.GetClrType(str))
    @clrtype.returns()
    def CustomerID(self, value):
        self._customerId = value

    @property
    @clrtype.accepts()
    @clrtype.returns(str)
    def CompanyName(self):
        return self._companyName

    @CompanyName.setter
    @clrtype.accepts(str)
    @clrtype.returns()
    def CompanyName(self, value):
        self._companyName = value

    @property
    @clrtype.accepts()
    @clrtype.returns(str)
    def ContactName(self):
        return self._contactName

    @ContactName.setter
    @clrtype.accepts(str)
    @clrtype.returns()
    def ContactName(self, value):
        self._contactName = value

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(ICollection)
    .MakeGenericType(Order))
    def Orders(self):
        return self._orders

    @Orders.setter
    @clrtype.accepts(clr.GetClrType(ICollection)
    .MakeGenericType(Order))
    @clrtype.returns()
    def Orders(self, value):
        self._orders = value

import clrtype
import clr
from System import *
from Entities.Customer import Customer

class Order(object):

    __metaclass__ = clrtype.ClrClass
    _clrnamespace = EntityFramework.Podo
    _clrfields = {  _customerId:str,
                    _orderId:int,
                    _orderDate:clr.GetClrType(DateTime),
                    _customer:clr.GetClrType(Customer)
                 }

    @property
    @clrtype.accepts()
    @clrtype.returns(int)
    def OrderID(self):
        return self._orderId

    @OrderID.setter
    @clrtype.accepts(int)
    @clrtype.returns()
    def OrderID(self, value):
        self._orderId = value

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(DateTime))
    def OrderDate(self):
        return self._orderDate

    @OrderDate.setter
    @clrtype.accepts(clr.GetClrType(DateTime))
    @clrtype.returns()
    def OrderDate(self, value):
        self._orderDate = value

    @property
    @clrtype.accepts()
    @clrtype.returns(str)
    def CustomerID(self):
        return self._customerId

    @CustomerID.setter
    @clrtype.accepts(str)
    @clrtype.returns()
    def CustomerID(self, value):
        self._customerId = value

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(Customer))
    def Customer(self):
        return self._customer

    @Customer.setter
    @clrtype.accepts(clr.GetClrType(Customer))
    @clrtype.returns()
    def Customer(self, value):
        self._customer = value

Notice the OrderDate property is specifying the System.DateTime data type? Let’s assume the above code will just work; if I run this ad-hoc proof of concept code below in Listing 2.0, I don’t encounter any problems and the output certainly seems to suggest that this should hang together ok when we hook our Customer and Order entities up via mapping to the Entity Framework.

Listing 2.0

import clrtype
import clr
from System import *

class ClrNatives(object):

    __metaclass__ = clrtype.ClrClass
    _clrfields =    {
                        _clrDate:clr.GetClrType(DateTime),
                        _clrInt32:clr.GetClrType(Int32)
                    }

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(Int32))
    def ClrInt32(self):
        print got into accessor
        return self._clrInt32

    @ClrInt32.setter
    @clrtype.accepts(clr.GetClrType(Int32))
    @clrtype.returns()
    def ClrInt32(self, value):
        print got into the mutator
        self._clrInt32 = value

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(DateTime))
    def ClrDate(self):
        print got into accessor
        return self._clrDate

    @ClrDate.setter
    @clrtype.accepts(clr.GetClrType(DateTime))
    @clrtype.returns()
    def ClrDate(self, value):
        print got into the mutator
        self._clrDate = value

c = ClrNatives()

print c.ClrDate.GetType()
print c.ClrInt32.GetType()

c.ClrInt32 = 10
c.ClrDate = DateTime.Now

print c.ClrInt32
print c.ClrDate

Figure 2.0

Figure 2.0 below depicts the output from the code in Listing 2.0 and shows that the underlying CLR type is indeed having the correct types created for it’s backing fields and associated properties.

image

The next piece of the puzzle that we would require would be the Entity Framework ObjectContext. Based on the recommended C# pattern for POCO implementation, we would do the following:

Listing 3.0

class NorthwindEntities(ObjectContext):

    __metaclass__ = clrtype.ClrClass
    _clrnamespace = EntityFramework.Podo
    _clrfields = {
                    _customers:clr.GetClrType(IObjectSet)
                        .MakeGenericType((Customer)),
                    _orders:clr.GetClrType(IObjectSet)
                        .MakeGenericType((Order))
                 }

    def __init__(self):pass

    def __init__(self, connectionString):
        self._customers = self.CreateObjectSet[Customer]()
        self._orders = self.CreateObjectSet[Order]()
        self.ContextOptions.LazyLoadingEnabled = True;

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(IObjectSet)
        .MakeGenericType((Customer)))
    def Customers(self):
        return self._customers

    @Customers.setter
    @clrtype.accepts(clr.GetClrType(IObjectSet)
        .MakeGenericType((Customer)))
    @clrtype.returns()
    def Customers(self, value):
        self._customers = value

    @property
    @clrtype.accepts()
    @clrtype.returns(clr.GetClrType(IObjectSet)
        .MakeGenericType((Order)))
    def Orders(self):
        return self._orders

    @Orders.setter
    @clrtype.accepts(clr.GetClrType(IObjectSet)
        .MakeGenericType((Order)))
    @clrtype.returns()
    def Orders(self, value):
        self._orders = value

Creating an ObjectContext in IronPython was straightforward, inherit from ObjectContext and create IObjectSet[T] backing fields and properties for the entities managed by the context. As I said earlier, this specialised IronPython ObjectContext follows the pattern set out for POCO development where a roughly equivalent C# version would be as follows:

public class NorthwindEntities : ObjectContext
{
    private IObjectSet<Customer> _customers;
    private IObjectSet<OrderLine> _orderLines;
    private IObjectSet<Order> _orders;

    public NorthwindEntities()
        : base("name=NorthwindEntities", "NorthwindEntities")
    {

    }

    public NorthwindEntities(string connectionString)
        : base(connectionString, "NorthwindEntities")
    {
        _customers = CreateObjectSet<Customer>();
        _orders = CreateObjectSet<Order>();
        _orderLines = CreateObjectSet<OrderLine>();
    }

    public IObjectSet<Customer> Customers
    {
        get
        {
            return _customers;
        }
    }

    public IObjectSet<OrderLine> OrderLines
    {
        get
        {
            return _orderLines;
        }
    }

    public IObjectSet<Order> Orders
    {
        get
        {
            return _orders;
        }
    }
}

The Mapping Problem

My original goal was to provide all the moving pieces in IronPython code, even the mapping. Entity Framework 4.0 has a code only option with mapping (no XML required) and that made sense – considering there would be no need to bring any managed C# libraries into the mix. Unfortunately however it’s not currently possible to work with Expression[Func[T]] in IronPython and so the code only mapping is just not going to happen for the moment. Hang on you say – what about all the use of Expressions in the Entity Framework itself? Good question. We are not going to use them! The Entity Framework allows the use of Query Builder methods that take strings as arguments, producing ObjectQuery[T] where T is the entity type.

Lets run It!

At this point we have all the constituent pieces required, all that’s left is to see is whether or not it actually works. We start with some simple client code (running in NetBeans Python Edition) to simply load up some Customers:

mappingPart = metadata=../Northwind.csdl|../Northwind.ssdl|../Northwind. + msl;
providerPart = provider=System.Data.SqlClient;provider connection 
dbPart1 = string=\”Data Source=BOOMER\\BOOM09;Initial Catalog=Northwind;
dbPart2 = Integrated Security=True;MultipleActiveResultSets=True\”
cn = mappingPart + providerPart + dbPart1 +dbPart2

ctx = NorthwindEntities(cn)

custs = ctx.Customers.Where(it.CustomerID > ‘C’)

for cust in custs:
    custOutput = The Customer ID is %(id)s and Company Name is %(name)s
    custOutTuple = {id: cust.CustomerID, name: cust.CompanyName}
    print custOutput % custOutTuple

Before we look at the result of running this code its worth noting one thing about this code above, the mapping portion of the connection string is pointing to a location on disk that specifies where to find the Entity Framework Mapping files. Remember that I said that we were unsuccessful in getting the code only mapping working due the issue with Expression Trees and IronPython. Entity Framework 4.0 does allow us produce mapping files with no code generated entities; this can be achieved in a C# or VB.NET library. Simply create your model in the VS designer as usual, make sure that it maps to your POCO’s in terms of structure, then build the project, specifying to export the mapping files rather than embedded them in the assembly.

Figure 3.0

image

In Visual Studio 2010 click on the .edmx file in Solution Explorer and remove the Custom Tool in the properties window so it becomes blank. Next, make the Copy to Output Director property either ‘Copy Always’ or ‘Copy if Newer’. Navigate to the output directory after running a build and you should see something similar to these three files (names will vary of course). These three files constitute the mapping.

Figure 4.0

image

Celebrations? Cigars?

So what output if any? Time to light up a cigar in celebration? What does the output window in NetBeans show us (see figure 4.0)?

Figure 5.0

image

Looks like we have been successful in getting the Entity Framework to speak directly to our IronPython class doesn’t it. Upon a quick check in SQL Profiler I could confirm that indeed the Customers were being loaded by our IronPython ObjectContext.

SELECT
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[CompanyName] AS [CompanyName],
[Extent1].[ContactName] AS [ContactName]
FROM [dbo].[Customers] AS [Extent1]
WHERE [Extent1].[CustomerID] > ‘C’

So after some fist pumping and jig dancing, I decided I should see how deep it really went. First thing to check for my mind was loading an entity graph deeper than one entity and also doing that with lazy and eager loading.

Lazy Load the Entity Graph

By making a small change to our code that consumes our IronPython ObjectContext class and iterating over the Order collection present in each Customer record, we would hope to see the Lazy Loading kick in? Drum Roll. Great tension in the air as we press F6 (don’t shoot me it’s NetBeans remember)……..

for cust in custs:
    print cust.CustomerID
    for order in cust.Orders:
        print OrderID

And sadly folks it blows up. What happened exactly? Interestingly enough, all the errors I had encountered up till this point when writing the proof of concept code, were related to mapping mistakes between the PODO’s (IronPython Entities) and my .csdl / .msl and .ssdl mapping files and therefore not insurmountable. This error was more than troubling and had me thinking we had struck a real road block that might not be movable. So how did the error manifest itself?

Figure 6.0

image

Unfortunately something about iterating the Customer Orders collection was blowing IPY.exe up and producing a crash dump file. I’m starting to believe in destiny just about now because just a week ago I happened across Scott Hanselman’s channel 9 interview of Tess Ferranadez who was demonstrating the new dump file debugging capabilities of VS 2010. Looks like I’m about to be checking that feature out a little earlier than I originally imagined.

Let’s hold that thought for a moment and revisit the code briefly before we embark on our voyage into dump files! The most obvious three things I saw as worthy for consideration as to the failure were, the iteration of Orders, something about the nature of the Order Entity itself or lazy loading was a goner? I started to examine the differences between the Customer and Order entities to look for differences that might proffer some clues. Immediately it was clear that the Customer entity only had strings for properties, surely that cant be it I thought, but decided to remove it from the list of possibilities immediately nonetheless. So after quickly testing the Order entity on it’s own (as the aggregate root) it became clear that indeed there might be a problem with primitives translating from Entity Framework over to the type declarations made in the IronPython classes.

orders = ctx.Orders.Where(it.CustomerID > ‘C’)
for order in Orders:
    print Order.CustomerID

Unfortunately where this was successful with Customer (all strings), it was not so with the Order entity which contained integers and Dates amongst them. Incredulous and unconvinced I decided to create a pure ad-hoc table with a mixture of primitives other than strings and this also confirmed my findings. Even when more exotic (tongue in cheek) types like DateTime were removed from the equation and only Int32 and String were present, the problem remained present.

A sanity check was required at this point. I recalled that I had a pre-existing proof of concept to show that specifying CLR types to the _clrfields and decorators were indeed working in other un-persisted entities, furthermore the IronPython class deriving from ObjectContext itself was example of this (see Listing 2.0 and 3.0). So what on earth was this snag? Using Python either int or clr.GetClrType(Int32) had the same negative effect, the Entity Framework didn’t seem to like either of them. This left me scratching a big whole in my head.

In an attempt to be complete, I still wanted to test lazy and eager loading. Let’s begin by moving our attention to a different Entity Model based on two tables where all the fields were typed as strings, that way I thought I could have a go at eager loading using the .Include(“Load.Path”) extension method which takes a string and returns an ObjectQuery[T] (<T> for C#). Here is the new model and query code.

image

parents = ctx.ParentRecords.Where(it.ParentID != ‘bob’).Include(ChildRecords)

for parent in parents:
    print parent.ParentID
    for child in parent.ChildRecords:
        print \t + child.ChildID

Success! Judging from the output from this query and iteration, eager loading does appear to work as expected:

Figure 7.0

image

The SQL Profiler confirms that eager loading has in fact worked as expected. I dislike the SQL that Entity Framework produces – but that’s a subject for a very different post, I just suddenly felt the need for a mini rant.

SELECT
[Project1].[C1] AS [C1],
[Project1].[ParentID] AS [ParentID],
[Project1].[ParentName] AS [ParentName],
[Project1].[C2] AS [C2],
[Project1].[ChildID] AS [ChildID],
[Project1].[ParentID1] AS [ParentID1],
[Project1].[ChildName] AS [ChildName]
FROM ( SELECT
    [Extent1].[ParentID] AS [ParentID],
    [Extent1].[ParentName] AS [ParentName],
    1 AS [C1],
    [Extent2].[ChildID] AS [ChildID],
    [Extent2].[ParentID] AS [ParentID1],
    [Extent2].[ChildName] AS [ChildName],
    CASE WHEN ([Extent2].[ChildID] IS NULL)
        THEN CAST(NULL AS int) ELSE 1 END AS [C2]
    FROM  [dbo].[ParentRecords] AS [Extent1]
    LEFT OUTER JOIN [dbo].[ChildRecords] AS [Extent2]
        ON [Extent1].[ParentID] = [Extent2].[ParentID]
    WHERE [Extent1].[ParentID] <> ‘bob’
)  AS [Project1]
ORDER BY [Project1].[ParentID] ASC, [Project1].[C2] ASC

How about Lazy Loading? Remember we set the Lazy Loading property of the ObjectContext options in the __init__ (see Listing 3.0 above). So let’s check and leave out the .Include() this time:

parents = ctx.ParentRecords.Where(it.ParentID != ‘bob’)

for parent in parents:
    print parent.GetType().FullName
    print parent.ParentID
    for child in parent.ChildRecords:
        print \t + child.ChildID

BOOM…no joy here! Let’s have a look at the output and see what went wrong this time.

Figure 8.0

image

We can see here that we are able to retrieve our ParentRecords without any problem however when ask for the ChildRecords for each Parent then we get a NoneType error, but we know for a fact that record ABCDE indeed has children as exhibited by our eager loading example. I feel myself about to descend down yet another rabbit hole. Lets make a quick check and see if a null check gets us past this point.

for parent in parents:
    print parent.GetType().FullName
    print parent.ParentID
    if parent.ChildRecords != None:
        for child in parent.ChildRecords:
            print \t + child.ChildID

Ok, so no error this time but still no lazy load, but at least are we getting closer to knowing the theory around the primitives is accurate?

How about the mapping what part is that playing in this primitives issue? I added an extra column to the ChildRecord table and use int as it’s data type. Let’s give the ChildRecord Entity an Int64 member whilst the mapping files retain the Int32 mapping. We would expect a mapping error to be reported right? As you can see below that’s exactly what we get.

Traceback (most recent call last):

  File C:\Users\simon.segal\Documents\NetBeansProjects\IronPythonEntityFramework\src\main.py, line 33, in C:\Users\simon.segal\Documents\NetBeansProjects\IronPythonEntityFramework\src\main.py

  File C:\Users\simon.segal\Documents\NetBeansProjects\IronPythonEntityFramework\src\Context.py, line 36, in __init__

SystemError: The type Edm.Int32 of the member ChildAgeInYears in the conceptual side type NorthwindModel.ChildRecord does not match with the type System.Int64 of the member ChildAgeInYears on the object side type EntityFramework.Podo.ChildRecord.

I also made a point of including some code to get a look at the Types full name and we can see that it’s the fully qualified name of the underlying CLR type as specified – that’s good you say, exactly what we want __clrtype__ to do for us. The problem with that is that the Entity Framework 4.0 dials up proxies at runtime when we use POCO, if you debug C# code you can see that asking for the POCO entities fully qualified name returns the proxy details as shown in Figure  9.0. This is not the case however for our IronPython Entities (see figure 8.0), regardless of our implementing __clrtype__.

Figure 9.0

image

In Part 3.0 we will dig into proxies and what they offer, how to setup to use them for different requirements and what effect it may or may not be having on our attempts to get POCO (or rather PODO) lazy loading and change tracking entities working with Entity Framework version 4.0.

Share/Save/Bookmark

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia