Initial POCO Design 1-Pager

Here is a raw cut and paste for our POCO 1-Pager. We are currently working through the design and have some prototype work going on and we would like to hear your feedback. Note this is the "feature design 1-Pager" not the "implementation design 1-Pager" we are still looking at the details for the design and at this point would love to hear feedback on the experience plus thought around state mgmt in general. We will post additional design notes for this feature after the upcoming team design meeting.

1. Overview

Persistence Ignorance refers to being able to allow the developer to write and test domain objects in a way that is entirely independent of fundamental requirements and assumptions that may be made by the infrastructure service (in this case, the Entity Framework). Such requirements / assumptions may often include:

  • The need to implement a specific interface (for e.g., IPOCO)
  • Inheritance from a base class
  • Providing specific constructors
  • Object Instantiation/Construction requirements – use a specific factory for instance
  • The need for metadata or mapping class or property Attributes
  • The need to use specific relationship mechanisms

This amounts to being able to use Plain Old CLR Objects (POCO) so that a developer can author their domain objects free of all assumptions and requirements imposed by the framework. Using this approach, once the domain objects are ready to their satisfaction, the developer can use these classes with the Entity Framework in order for relational database access and persistence.

2. Context

While the customization of entity types has always been a goal with Entity Framework, v1 imposed several restrictions/requirements in terms of how the entity types had to be built – for instance, at the minimum, a few interfaces had to be implemented at a minimum:

  • IEntityWithRelationships
  • IEntityWithChangeTracking

Pure POCO should eliminate the need to implement these interfaces.

In addition, POCO shouldn’t require the use of attributes that are required to map object members to the C-space.

3. Design

When the Entity Framework supports Persistence Ignorance in the form of pure POCO, entity classes that are free of any infrastructure related artifacts can be authored as shown. The following example shows a Customer entity and an Order entity. There is a relationship between Customer and Order – i.e. a Customer can have many Orders.

O-Space to C-Space mapping is done by convention – i.e. the CLR types of the entities below map to the corresponding entities already defined in the Conceptual Model.

     public class Customer
    {
        string _CustomerID;
        string _ContactName;
        string _City;
        List<Order> _Orders;

        public string CustomerID
        {
            get { return _CustomerID; }
            set { _CustomerID = value; }
        }

        public string ContactName
        {
            get { return _ContactName; }
            set { _ContactName = value; }
        }

        public string City
        {
            get { return _City; }
            set { _City = value; }
        }

        public List<Order> Orders
        {
            get { return _Orders; }
            set { _Orders = value; }
        }
    }
     public class Order
    {
        int _OrderID;
        Customer _Customer;
        DateTime _OrderDate;

        public int OrderID
        {
            get { return _OrderID; }
            set { _OrderID = value; }
        }

        public Customer CustomerID
        {
            get { return _CustomerID; }
            set { _CustomerID = value; }
        }

        public DateTime OrderDate
        {
            get { return _OrderDate; }
            set { _OrderDate = value; }
        }
    }

Once the POCO classes are in place, one can program against them as first class entity objects.

For instance, query can be used to materialize POCO objects as shown:

         var query = from c in db.Customers.Include("Orders")
                    where c.City == "London"
                    select c;

ObjectContext can be used for CUD operations much like the usage patterns supported today:

         Customer customer = new Customer();
        customer.City = "London";
        customer.ContactName = "Steve";
        customer.CompanyName = "Acme";

        Order order = new Order();
        order.OrderDate = DateTime.Today;

        customer.Orders.Add(order);

        db.AddObject("Customers", customer);
        db.SaveChanges();

Tim Mallalieu
Program Manager,
Entity Framework Team

This post is part of the transparent design exercise in the Entity Framework Team. To understand how it works and how your feedback will be used please look at this post .