EF4 TechTalk Slides and Demos

I gave a Microsoft TechTalk this wednesday on Entity Framework 4.0, and I promised to make the slides and code available from my blog, so here they are.

As i said at the talk, you are most welcome to write me if you have any follow up questions.

Posted October 16, 2009 by Joachim Lykke Andersen
In EF4

Comments [0]   

Danish Podcast: Entity Framework 4.0 Beta 1

A while ago I was on AnugCast with Søren Spelling Lund and talked about Entity Framework 4.0, and now its been released.

We talk about version 1, Vote of no confidence, what happened to version 2 and 3, the road to 4.0, and of course all the new stuff like POCO, Model First, Deferred Load, T4 templates, Persistance ignorance support, Code only etc.

Download: [DK] ANUGCast #41 Entity Framework 4.0 med Joachim Lykke Andersen

Posted August 3, 2009 by Joachim Lykke Andersen
In EF4 | Entity Framework

Comments [0]   

Entity Framework 4.0 Beta 1 – POCO Enum support?

One of the things that has not made it into Entity Framework 4.0 beta 1 is Enum support and it is not planned for EF4.

This seems like a strange decision, as it is wrong and not POCO at all if you have to change your classes to work around the lack of enum support in your persistance layer.

Around the internet people suggest that you can just make the property private, and then create a public property that exposes your value as your enum. But that is not quite the solution, as this is not going to work in Linq queries that execute at database level.

While I was still trying to work around this, I came across this post by Alex James that does exactly what I was attempting: to fake enum support.

Lets see how this will look if we implement our Status property on the Order entity to be an enum.

The first thing we are going to do, is to change our Status property in the EF model to be a complex type. We can do that in the designer.

image

First of all we create the complex type. Right click “Complex Types” in the model browser and choose “Create Complex Type”. We name it OrderStatusWrapper and add a scalar Int32 property called “Value” to it.

Then we delete the scalar Status property from the Order entity, and add a complex property instead. We name it Status like the old one, and in properties we set the type to “OrderStatusWrapper”. If we build now, the validator will complain that we forgot to map the property, so we get the table mapping window, and map the Status integer to the “Value” integer on our complex property.

image

 

 

 

 

 

 

 

 

 

 

Now we add the enum as usually:

    3 public enum OrderStatus

    4 {

    5     OrderCreated,

    6     OrderPayed,

    7     OrderShipped

    8 }

Now we have to implement our OrderStatusWrapper, and make it do some work behind the scenes for us:

    1 

    2 public class OrderStatusWrapper

    3 {

    4     private OrderStatus _status;

    5 

    6     public int Value

    7     {

    8         get { return (int)_status; }

    9         set { _status = (OrderStatus)value; }

   10     }

   11     public OrderStatus EnumValue

   12     {

   13         get { return _status; }

   14         set { _status = value; }

   15     }

   16 

   17     public static implicit operator

   18         OrderStatusWrapper(OrderStatus status)

   19     {

   20         return new OrderStatusWrapper { EnumValue = status };

   21     }

   22 

   23     public static implicit operator

   24         OrderStatus(OrderStatusWrapper statusWrapper)

   25     {

   26         if (statusWrapper == null) return

   27             OrderStatus.OrderCreated;

   28         else return statusWrapper.EnumValue;

   29     }

   30 }

   31 

To do this we need to do an implicit operator overloading – that is an implicit conversion between OrderStatusWrapper and OrderStatus, creating the illusion that Status really is an OrderStatus enum value.

Now we can actually do this:

   24             Order o = new Order();

   25             o.CreatedDate = DateTime.Now;

   26             o.Status = OrderStatus.OrderCreated;

   27             o.Customer = custRep.First(x => x.Id == 1);

   28             orderRep.Add(o);

And we can use it in a query like so:

   24 var orders = from o in orderRep.GetAll()

   25              where o.Status == OrderStatus.OrderCreated

   26              select o;

This is a fairly decent workaround, but it still bothers me that we have to declare our property with the type of the wrapper, and that we have to clutter our code with wrappers. This is behaviour to accommodate our choice of ORM.

So we do need real enum support, but intill we do we seem to get by with this.

Resources:

Speaking at ANUG on Entity Framework 4.0 Beta 1 – Hands on look on the new bits

I will be speaking at the June meeting of ANUG covering the new bits in Entity Framework 4.0 Beta 1.

When:
25/6 18:00

Where:
Kamstrup A/S
Industrivej 28, Stilling
DK-8660 Skanderborg

Sign Up

It will be pretty hands on with focus on demoing the new stuff, starting out from the criticism of the first version of EF, to the wishlist for the next version.

Hope to see you there.

Entity Framework 4.0 Beta 1 – POCO, ObjectSet, Repository and UnitOfWork

In the old Entity Framework, creating a generic repository wasn’t impossible, but not really elegant either. Any way you looked at it, you needed to deal with strings to get it working.

Lets say you want to create an Add method on your repository, there was no way getting around something like this:

    6 

    7         objectContext.AddObject("OrderSet", newOrder)

    8 

So for each (base) entity you have in your conceptual model you have a corresponding EntitySet, and in EF1 you needed to pass in the string name of the entityset to add the object; the name is not necessarily the same as the name of the entity.

In a generic repository you would have to figure out the name of the current entityset – you can figure it out with a bit of reflection on the concrete ObjectContext, but its not pretty, errorprone and it took me a while to get there.

Enter ObjectSet<T>

Fortunately in EF4 the strongly typed properties on the ObjectContext for each EntitySet return ObjectSet<T> instead of ObjectQuery<T>. And since the ObjectContext also has a method called CreateObjectSet<T> you can instead do something like this:

    1 

    2 private IObjectSet<T> ObjectSet

    3 {

    4     get

    5     {

    6         if (_objectSet == null)

    7         {

    8             _objectSet = this.Context.CreateObjectSet<T>();

    9         }

   10         return _objectSet;

   11     }

   12 }

   13 

   14 public void Add(T entity)

   15 {

   16     this.ObjectSet.AddObject(entity);

   17 }

   18 

Notice the IObjectSet<T>  which is very handy as it enables you to fake the ObjectSet for testing for instance. Now to be fair, this is how it should have been in EF1, but on an optimistic note im happy its changed.

Repository<T>

In order to have the right context for testing EF4 properly with persistance ignorance and POCO we will set up a Repository and UnitOfWork pattern for the OrderModel project i did in my previous EF4 post. Im not going to cover every detail of this, but I will run through the setup, and then you can get the code and have a closer look on your own.

First i set up the repository contract and create an IRepository<T> where T is a POCO class.

    1 

    2 public interface IRepository<T> where T : class

    3 {

    4     IQueryable<T> GetQuery();

    5 

    6     IEnumerable<T> GetAll();

    7     IEnumerable<T> Find(Func<T, bool> where);

    8     T Single(Func<T, bool> where);

    9     T First(Func<T, bool> where);

   10 

   11     void Delete(T entity);

   12     void Add(T entity);

   13     void Attach(T entity);

   14     void SaveChanges();

   15 }

   16 

Next we will define a generic repository for the Entity Framework that implements IRepository<T>:

    1 

    2 public class EFRepository<T> : IRepository<T> where T : class

    3 {

    4     ObjectContext _context;

    5     IObjectSet<T> _objectSet;

    6 

    7     private ObjectContext Context

    8     {

    9         get

   10         {

   11             if (_context == null)

   12             {

   13                 _context = GetCurrentUnitOfWork

   14                     <EFUnitOfWork>().Context;

   15             }

   16             return _context;

   17         }

   18     }

   19 

   20     private IObjectSet<T> ObjectSet

   21     {

   22         get

   23         {

   24             if (_objectSet == null)

   25             {

   26                 _objectSet = this.Context

   27                     .CreateObjectSet<T>();

   28             }

   29             return _objectSet;

   30         }

   31     }

   32 

   33     public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>()

   34         where TUnitOfWork : IUnitOfWork

   35     {

   36         return (TUnitOfWork)UnitOfWork.Current;

   37     }

   38 

   39     public IQueryable<T> GetQuery()

   40     {

   41         return ObjectSet;

   42     }

   43 

   44     public IEnumerable<T> GetAll()

   45     {

   46         return GetQuery().ToList();

   47     }

   48 

   49     public IEnumerable<T> Find(Func<T, bool> where)

   50     {

   51         return this.ObjectSet.Where<T>(where);

   52     }

   53 

   54     public T Single(Func<T, bool> where)

   55     {

   56         return this.ObjectSet.Single<T>(where);

   57     }

   58 

   59     public T First(Func<T, bool> where)

   60     {

   61         return this.ObjectSet.First<T>(where);

   62     }

   63 

   64     public void Delete(T entity)

   65     {

   66         this.ObjectSet.DeleteObject(entity);

   67     }

   68 

   69     public void Add(T entity)

   70     {

   71         this.ObjectSet.AddObject(entity);

   72     }

   73 

   74     public void Attach(T entity)

   75     {

   76         this.ObjectSet.Attach(entity);

   77     }

   78 

   79     public void SaveChanges()

   80     {

   81         this.Context.SaveChanges();

   82     }

   83 }

   84 

Now thats pretty straight forward. The ObjectContext actually already works like a UnitOfWork, but in order to handle the lifespan of our ObjectContext we wrap it up in our own UnitOfWork implementation.

    1 

    2 public class EFUnitOfWork : IUnitOfWork, IDisposable

    3 {

    4     public ObjectContext Context { get; private set; }

    5 

    6     public EFUnitOfWork(ObjectContext context)

    7     {

    8         Context = context;

    9     }

   10 

   11     public void Commit()

   12     {

   13         Context.SaveChanges();

   14     }

   15 

   16     public void Dispose()

   17     {

   18         if (Context != null)

   19         {

   20             Context.Dispose();

   21         }

   22         GC.SuppressFinalize(this);

   23     }

   24 }

   25 

IUnitOfWork consists of the method  Commit, and in our concrete implementation we save changes on our current ObjectContext on commmit.

To handle units of work we implement a static class that handles both the case of a webcontext and a multithreaded non web context. The ObjectContext is not threadsafe, so we need to take that in consideration.

The interesting bit of that class is the Current property that gets the current UnitOfWork:

    1 

    2 public static IUnitOfWork Current

    3 {

    4     get

    5     {

    6         IUnitOfWork unitOfWork = GetUnitOfWork();

    7         if (unitOfWork == null)

    8         {

    9             _unitOfWorkFactory = ObjectFactory.

   10                         GetInstance<IUnitOfWorkFactory>();

   11             unitOfWork = _unitOfWorkFactory.Create();

   12             SaveUnitOfWork(unitOfWork);

   13         }

   14         return unitOfWork;

   15     }

   16 }

   17 

We are going to look at the two methods that do the work in a moment, but first of all notice that we have a UnitOfWorkFactory to produce our specific UnitOfWork. Furthermore we are going to use the StructureMap Service Locator to get our dependency on a concrete factory.

Either in configuration or in code we need to set up which concrete type the requested type should resolve to like so. In code it would be something like this:

    2 

    3 ObjectFactory.Initialize(

    4     x =>

    5     {

    6         x.ForRequestedType<IUnitOfWorkFactory>().

    7             TheDefaultIsConcreteType<EFUnitOfWorkFactory>();

    8 

    9         x.ForRequestedType(typeof(IRepository<>)).

   10             TheDefaultIsConcreteType(typeof(EFRepository<>));

   11     }

   12 );

   13 

We map it to the concrete factory implementation for our Entity Framework project. The IRepository<T> is also mapped to the concrete type EFRepository that we created earlier.

The EFUnitOfWork factory has the responsibility of creating new units of work, implements the IUnitOfWorkFactory and has a method that takes a delegate which, when called creates an instance of the ObjectContext we want to work on.

    1 

    2 public class EFUnitOfWorkFactory : IUnitOfWorkFactory

    3 {

    4     private static Func<ObjectContext> _objectContextDelegate;

    5     private static readonly Object _lockObject = new object();

    6 

    7     public static void SetObjectContext

    8         (Func<ObjectContext> objectContextDelegate)

    9     {

   10         _objectContextDelegate = objectContextDelegate;

   11     }

   12 

   13     public IUnitOfWork Create()

   14     {

   15         lock (_lockObject)

   16         {

   17             ObjectContext context = _objectContextDelegate();

   18         }

   19         return new EFUnitOfWork(context);

   20     }

   21 }

   22 

UnitOfWork/ObjectContext lifespan

So back to the UnitOfWork. As mentioned the ObjectContext is not threadsafe, so we need to make sure that when re-using the objectcontext we dont run into issues with that.

If we are in a web-application we probably want to at least scope the context to maximum the lenght of the request. If we tied it to a static class member, it would share lifespan with the AppDomain and that is bound to cause problems.

Maybe it would make sense to work in smaller cohesive chunks of one or few business transactions and you could create a UnitOfWork scope to handle that, but for the sake of the example we are going to tie it to HttpContext.Current.Items and thereby limit the lifespan to the current request.

When we are not in a web application we need to handle multithreaded scenarios at least, and it would probably make most sense to have a scope of a business transaction, but in this context ill just handle the threading issue. This leaves us with the following methods on UnitOfWork where _threads is a Hashtable:

    1 

    2 private static IUnitOfWork GetUnitOfWork()

    3 {

    4     if (HttpContext.Current != null)

    5     {

    6         if (HttpContext.Current.Items.

    7                     Contains(HTTPCONTEXTKEY))

    8         {

    9             return (IUnitOfWork)HttpContext.Current.

   10                                     Items[HTTPCONTEXTKEY];

   11         }

   12         return null;

   13     }

   14     else

   15     {

   16         Thread thread = Thread.CurrentThread;

   17         if (string.IsNullOrEmpty(thread.Name))

   18         {

   19             thread.Name = Guid.NewGuid().ToString();

   20             return null;

   21         }

   22         else

   23         {

   24             lock (_threads.SyncRoot)

   25             {

   26                 return (IUnitOfWork)_threads

   27                     [Thread.CurrentThread.Name];

   28             }

   29         }

   30     }

   31 }

   32 

   33 private static void SaveUnitOfWork(IUnitOfWork unitOfWork)

   34 {

   35     if (HttpContext.Current != null)

   36     {

   37         HttpContext.Current.Items

   38                     [HTTPCONTEXTKEY] = unitOfWork;

   39     }

   40     else

   41     {

   42         lock(_threads.SyncRoot)

   43         {

   44             _threads[Thread.CurrentThread.Name] = unitOfWork;

   45         }

   46     }

   47 }

   48 

Conclusion

So we end up being able to write the following code:

    5 IRepository<Order> orderRep = ObjectFactory.

    6     GetInstance<IRepository<Order>>();

    7 IRepository<Customer> custRep = ObjectFactory.

    8     GetInstance<IRepository<Customer>>();

    9 

   10 Order o = new Order();

   11 o.CreatedDate = DateTime.Now;

   12 o.Status = 100;

   13 o.Customer = custRep.First(x => x.Id == 1);

   14 orderRep.Add(o);

We are programming against the interfaces and we use our POCO classes. We hook up our concrete DB dependend implementations with the StructureMap Service Locator, and we have control over the scope and lifespan with our UnitOfWork implementation.

But have a look at the code. Be advised though - it is not production ready code – it needs tests, guards and errorhandling, and it serves only as a sort of Proof of concept for EF4.

Entity Framework 4.0 Beta 1 – POCO Lazy Load and Code Generation of ObjectContext

In my first post about the 4.0 beta 1 bits I explored how we can work with our own POCO classes with the Entity Framework. In this post I will expand the example a little and figure out if and how we can do automatic lazy loading. Furthermore i will see if I can use the build in T4 template support to autogenerate an ObjectContext for our POCO entities.

The Model

I want to create a common scenario with an order, orderline, product and customer, so I start out with writing the following classes:

    1 public class Customer

    2 {

    3     public virtual ICollection<Order> Orders { get; set; }

    4     public virtual int Id { get; set; }

    5     public virtual string FirstName { get; set; }

    6     public virtual string LastName { get; set; }

    7     public virtual string Address { get; set; }

    8     public virtual string Email { get; set; }

    9 }

   10 public class Order

   11 {

   12     public virtual ICollection<OrderLine>

   13         OrderLines { get; set; }

   14     public virtual Customer Customer { get; set; }

   15     public virtual int Id { get; set; }

   16     public virtual DateTime CreatedDate { get; set; }

   17     public virtual int Status { get; set; }

   18 }

   19 public class OrderLine

   20 {

   21     public virtual Product Product { get; set; }

   22     public virtual Order Order { get; set; }

   23     public virtual int Id { get; set; }

   24     public virtual double ItemPrice { get; set; }

   25     public virtual int Quantity { get; set; }

   26 }

   27 public class Product

   28 {

   29     public virtual ICollection<OrderLine>

   30         OrderLines { get; set; }

   31     public virtual int Id { get; set; }

   32     public virtual string Name { get; set; }

   33     public virtual string Description { get; set; }

   34     public virtual double Price { get; set; }

   35 }

Then I go ahead and create the Entity Framework Model exactly like the Poco classes.

image

Notice the navigation properties have the right pluralization. If you generate your Entity Model from an existing database notize that you now have the option to pluralize or singularize generated object names:

image

T4 Code Generation

This time I dont want to manually write my objectcontext implementation. I want to code generate it, so that when i update my Entity Model the ObjectContext is automatically updated as well.

In version 1.0 of the Entity Framework you had to create a SingleFileGenerator and hook into EFs codegeneration events, and it was not a very likeable costumization story. Because of all the feedback on this, The ADO.Net Team decided to handle code generation with T4 templates instead.

This is truly sweet, and as it is deeply integrated with the Entity Framework its very easy to get started. As an example we will add a t4 template generator to our project and modify it to work with our POCO classes.

image

First we select our .edmx file and go to the entity designer. Then we right-click anywhere on the workarea and choose “Add new Artifact Generation Item”. Then we choose the ADO.NET EntityObject Generator:

image

This creates a .tt file with a sub .cs file. The .tt file is the template and the sub cs. file is the result of running the code generation on the template. When you change the .tt file and save the .cs file will be updated – you can also right click the .tt file and choose “Run custom tool”.

Now we open op the template file, and its not really as nice an interface as we are used to with Visual Studio – no syntax-highlighting or intellisense really makes it a challenge to edit:

image

To fix that we use the brand new Extension Manager (Tools > Extension Manager) in Visual Studio to get the Free Edition of the Tangible T4 editor – its not as feature rich as the Clarius Visual T4 one, but its free and a huge improvement:

image

This makes our template file look a lot more appealing, and the intellisense is simply invaluable – trust me, you need this one. The .tt file now looks like this:

image

So now we are equipped to remove the bits of the code generation that we don’t want. We want to get rid of any entities being generated and leave only the context bits. Its basically three sections that need to go - see the attached project for the resulting file. We also need to add an import to the namespace that contains our Poco classes, as so that these classes are used instead of the generated entities that we just have removed.

Requirements for Using Persistence-Ignorant Objects

In order to support deferred loading of related objects and change tracking some requirements do need to be fulfilled by the POCO classes.

What happens behind the scenes is, that a proxy object is created that inherits from your POCO object. This proxy object is responsible for handling lazy loading and change tracking. The requirements are:

  • Poco class must be public, and not sealed or abstract, and implement a default constructor with no parameters.
  • Poco class must NOT implement IEntityWithChangeTracker or IEntityWithRelationShips.
  • Poco class properties mapped to conceptual model must be public and virtual.
  • The mapped Navigational property must be declared virtual and must not be sealed.
  • One-to-Many and Many-to-Many navigational property (OrderLine on Order for instance)  must be mapped to properties that return a type implementing ICollection.

There are actually generated two kinds of proxies: One that handles lazy loading and one that handles change tracking. If you only mark navigational properties virtual, you will not get the change tracking proxies.

Eager Load vs. Lazy Load

So now we want to try out out, and we could do something like this:

    1 

    2using (var context = new OrderModelContainer())

    3{

    4     var orders = from o in context.OrderSet select o;

    5 

    6     foreach (var order in orders)

    7     {

    8         Console.WriteLine(order.CreatedDate);

    9         foreach (var orderline in order.OrderLines)

   10         {

   11             Console.WriteLine("  " + orderline.Quantity

   12                         + " " + orderline.Product.Name

   13                         + " of $" + orderline.ItemPrice);

   14         }

   15     }

   16 }

We try to print the orderlines for each order – but the result is without the orderlines:

image

In Entity Framework version 1.0 we would have to explicitly eager load the related objects, and you can of course still do this:

    6 var orders = from o in

    7              context.OrderSet.Include("OrderLines.Product")

    8              select o;

In many situations this is a good thing, as you have control over how many times your database is hit on a query, but it also clutters your code with at lot of explicit includes, and more often than not developers are surprised that the related collection of objects – orderlines for instance – is empty when called. It just seems more logical with lazy loading.

So instead you can now in EF4 decide to let the related objects load silently when they are called, resulting of course in further calls to the DB.

The lazy load or deferred load option is set on the context, and is disabled by default:

    1 using (var context = new OrderModelContainer())

    2 {

    3     context.ContextOptions.DeferredLoadingEnabled = true;

    4 

    5     var orders = from o in context.OrderSet select o;

    6 

    7     foreach (var order in orders)

    8     {

    9         Console.WriteLine(order.CreatedDate);

   10         foreach (var orderline in order.OrderLines)

   11         {

   12             Console.WriteLine("  " + orderline.Quantity

   13                         + " " + orderline.Product.Name

   14                         + " of $" + orderline.ItemPrice);

   15         }

   16     }

   17 }

Both the eager loaded and the lazy loaded produces the following result:

image

Setting the lazy load on the context seems very limited, and it would be much more helpful to the developer in a real world scenario if you could define the load strategy per navigation property.

The best that i can see as an option is that you enable lazy loading, and then handle the cases you know are going to do a lot of DB roundtrips with eager loading and do a sort of combo.

All in all i still think that EF4 is gigantic leap forward, and so far it has been surprisingly easy to make everything run as expected.

Resources

Entity Framework 4.0 – How To POCO

I have been looking forward to this for a while, and tonight i finally got around to installing Visual Studio 2010 and .Net 4.0 Beta 1 – including the new Entity Framework bits.

You may remember that i was not completely sold on Entity Framework 1.0, and neither was a big part of the developer community, so there are of course a lot of areas that I am really looking forward to explore in this coming version of the framework.

First and foremost I was very curious as to whether the Entity Framwork offers the promised POCO scenario, so as a first encounter I set of to figure out if this is the case or not.

I started out with creating a solution with only one project called “Model” containing a single class “Customer”:

    6 namespace EntityFrameworkPoco.Model

    7 {

    8     public class Customer

    9     {

   10         public int Id { get; set; }

   11         public string FirstName { get; set; }

   12         public string LastName { get; set; }

   13         public int Age { get; set; }

   14     }

   15 }

So now I have defined a simple Poco class that i want to use with the Entity Framework. I am not going to change this class in any way.

Next step is to create the model. I can create the metadata files myself or I can use the designer. I dont have a database with customers, and as I want to test another feature of the new Entity Framework I go with the designer:

So I create another project that I call EntityFramework, and to that i add a new ADO.Net Entity Data Model.

image

I select the .edmx file in the solution explorer, and in the Entity Framework Designer interface i create my Customer entity replicating my actual POCO entity, and as i dont have a database for my customers i right click and choose “Generate Database Script from Model”.

image

I choose my database connection and let it create a new database for me. The dialog then generates the SQL script needed to create the model in my database. Neat.

image

So now I have plugged in the EF to allow me to persist my POCO object to database, and materialize it back to me. One thing we need to remember is, that we don’t want the Entity Data Model we just created, to generate code for us – we want to handle that ourselves – well at least for now.

image 

Therefore we remove the “Custom Tool” that generates the code. Just delete the content of the property. This turns of code generation for the model.

So far so good. Now we need to hook it all up. We are going to need a context implementation now that it is not generated for us. So lets create the the CustomerContext on our EntityFramework project and let it expose a collection of our POCO Customers – an ObjectSet of Customer that is:

   10 public class CustomerContext : ObjectContext

   11 {

   12     private ObjectSet<Customer> _customers;

   13 

   14     public CustomerContext():

   15         base("name=CustomerModelContainer",

   16              "CustomerModelContainer")

   17     {

   18         _customers

   19             = CreateObjectSet<Customer>();

   20     }

   21 

   22     public ObjectSet<Customer> Customers

   23     {

   24         get

   25         {

   26             return _customers;

   27         }

   28     }

   29 

   30 }

Too simple of course, but for now it will let us fetch customers from database. Behind the scenes i cheat and create a few in the database, so that we can test it.

   36 static void Main(string[] args)

   37 {

   38     var context = new CustomerContext();

   39     var customers = from c in context.Customers

   40                     select c;

   41 

   42     foreach (var customer in customers)

   43     {

   44         Console.WriteLine(customer.FirstName);

   45     }

   46     Console.ReadKey();

   47 }

Which results in the following output.

image

Now if we want to add new customers we could add a method to our context like so:

   50 public void AddCustomer(Customer customer)

   51 {

   52     _customers.AddObject(customer);

   53 }

Which enables us to add a new customer:

   41 var newCustomer = new Customer();

   42 newCustomer.FirstName = "Jim";

   43 newCustomer.LastName = "Test";

   44 newCustomer.Age = 42;

   45 context.AddCustomer(newCustomer);

   46 context.SaveChanges();

This is of course a very superficial example of POCO with the entity framework, but it is indeed very promising. I will be looking further into some more advanced examples in the near future.

MSDN Blogger of the Year – Please Vote

In the latest MSDN Flash newsletter candidates are wanted for Blogger of the Year for 2008.

So please vote for your favorite blog by writing an email to dorthelk@microsoft.com with the name of the blog and blogger you think deserves the title of the best blog of the year.

If you have enjoyed posts on my blog I would be very grateful for your vote ;)

Posted December 14, 2008 by Joachim Lykke Andersen
In

Comments [0]