locked
What's the difference between POCO and code-first? RRS feed

  • Question

  • I've had some experience of using EF's database-first in a small project. Now I'd like to try out the code-first in another small project. But EF4.1 provides the support for POCO objects.

    It looks like both methodologies only require pure coding and no visual model designer is involved. So anyway, what's different?

    Thanks,

    Nico


    You Can't Stop Me!
    Thursday, June 23, 2011 8:32 AM

Answers

  • Every ORM framework has some requirements on class you want to use as entity. EF code first uses POCO classes. You have full control over your classes - that makes them POCO. Requirement of ICollection is obvious because framework has to know how to work with your collections. Without such requirement you will have to reimplement part of ORM in each application to teach EF how to access your special "collections". Using ICollection as a base interface for collection based classes is best practice in .NET and correct design. Using virtual properties is requirement only if you want to use dynamic proxies (lazy loading and dynamic change tracking).

    Best regards,
    Ladislav

    • Marked as answer by buaaytt Tuesday, June 28, 2011 2:25 AM
    Monday, June 27, 2011 7:24 AM
  • IMO the idea is wether or not you have some code in your class that explicitely support persistence (as this is the case if the class must inherit from a base class). Using ICollection to represent a collection seems something that makes sense even if you don't intend to persist the class and I don't think it's qualify as having been explicitely designed for persistence.

    Now it's still likely that each ORM will have its own default conventions and that you won't be necessarily be able to persist a class with each and every ORM without doing some changes. Hopefully you won't have to change your code if it could be done by providing some metadata to the ORM that describes your intent (or even some generic rules ?) or you could create your code to be prepared for that (using your own interface that could itself inherit from the particular interface(s) an ORM needs ?)

    At some point, perhaps some organization will try to establish and spread common conventions accross ORMs ?


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
    • Marked as answer by buaaytt Tuesday, June 28, 2011 2:24 AM
    Monday, June 27, 2011 9:48 AM

All replies

  • Hello,

    database first uses EDMX file for describing whereas code-first uses mapping in the code. Pure code first doesn't define database. You will write a code and EF will created database for you. Because of that it doesn't support many features like database views or mapping stored procedures or SQL functions. Code first is also mostly used with new DbContext API.

    Best regards,
    Ladislav

    Thursday, June 23, 2011 1:21 PM
  • Thanks Ladislav. I might not express my question clearly enough. I wanted to know the difference between the concept 'POCO with EF' and 'Code-first'. I know of the code-first mechanism itself, more or less.
    You Can't Stop Me!
    Friday, June 24, 2011 8:54 AM
  • I'm not sure what you are looking for - POCO stands for plain old CLR class and the concept is always the same. Class where you have control over its base type and implemented interfaces so it doesn't have to use any API specific features - that works same in whole EF. Code first is still EF and it uses internally same infrastructure like EDMX so there is no difference. Difference is how these classes are mapped to the database.

    Best regards,
    Ladislav

    Friday, June 24, 2011 1:36 PM
  • Lemme ask this way. If I used Code first to develop, can I say the entity classes I wrote with Code first are POCO classes? My gut feeling tells me they are somewhat different. But I can't find out the exact difference.
    You Can't Stop Me!
    Sunday, June 26, 2011 4:32 AM
  • Hi:

    Code First don't generate POCO classes. When you declare navigation porperty as virtual to get Lazy Loading feature, the DbContext don't return POCO objects, because it need to access Db when you acces to navigation property. Look user declaration

     public class User
     {
     public User()
     {
     Movements = new List<Movement>();
     }
    
     public int Id { get; set; }
    
     public string Name { get; set; }
    
     public virtual ICollection<Movement> Movements { get; set; }
     }
    
     public class Movement
     {
     public int Id { get; set; }
    
     public DateTime CreationTime { get; set; }
    
     public User User { get; set; }
     }
    
    now run this simple test
     HelloContext helloContext = new HelloContext();
     User user = helloContext.Users.First();
    
     Assert.AreEqual(typeof(User), user.GetType());
    

    This test fail, DbContext make runtime inherintance, to make Movements Property Lazy Load !

    The test result is;

    Assert.AreEqual failed. Expected:<Dal.User>. Actual:<System.Data.Entity.DynamicProxies.User_814F350E3EC8CEE20C8A346038BD78948AB650B8BCF529195AE0D5BA3E2E1F31>.

    Best Regards

    Sunday, June 26, 2011 5:44 AM
  • Niko, thanks for the reply.

    Yes, i'm aware of the interference that EF does in terms of the proxy object creation. What confused me a lot is that the above code looks very much like a POCO class. So what should a POCO-style code look like to represent the User and Movements relationship you used as the example? And how could we achieve lazy loading for POCO classes as well?


    You Can't Stop Me!
    Sunday, June 26, 2011 10:25 AM
  • Yes, POCO just means that your classes don't have to inherit from some base class to provide persistance features so yes in most if not all cases POCO goes with code first and the other way round.

    For lazy loading with POCO see : http://blogs.msdn.com/b/adonet/archive/2009/05/28/poco-in-the-entity-framework-part-2-complex-types-deferred-loading-and-explicit-loading.aspx

    Note also that you could use Code First against an existing database (Code First could create the database for you but if you could also have an existing database that matches the POCO classesyou are writing).

    You could also create POCO classes from a database.


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
    Sunday, June 26, 2011 4:44 PM
  • Thanks, Patrice. I think the term POCO is not 100% accurate, because there still seems to be some requirements that a POCO class has to match in order to work with EF. So it's not exactly an "plain old classes".

    Such a requirement is that if the navigation property represents a list of other objects, it has to be some collection class that implements ICollection<T> interface. An unrealistic scenario is that my POCO class might indeed have such a navigation property of a list of other objects, but it doesn't implement ICollection<T> interface somehow. So although it still has methods like Add, Remove, etc, it just doesn't implement ICollection<T> interface. In this case, it is still a plain old class, but it may not be able to work with EF.

    My understanding is that a real POCO class should imply that the DAL framework is interchangeable. If some day I want to replace EF with some other DAL framework, I don't need to change any code in POCO classes. That's a real POCO class.

    -Nico-


    You Can't Stop Me!
    Monday, June 27, 2011 6:20 AM
  • Every ORM framework has some requirements on class you want to use as entity. EF code first uses POCO classes. You have full control over your classes - that makes them POCO. Requirement of ICollection is obvious because framework has to know how to work with your collections. Without such requirement you will have to reimplement part of ORM in each application to teach EF how to access your special "collections". Using ICollection as a base interface for collection based classes is best practice in .NET and correct design. Using virtual properties is requirement only if you want to use dynamic proxies (lazy loading and dynamic change tracking).

    Best regards,
    Ladislav

    • Marked as answer by buaaytt Tuesday, June 28, 2011 2:25 AM
    Monday, June 27, 2011 7:24 AM
  • IMO the idea is wether or not you have some code in your class that explicitely support persistence (as this is the case if the class must inherit from a base class). Using ICollection to represent a collection seems something that makes sense even if you don't intend to persist the class and I don't think it's qualify as having been explicitely designed for persistence.

    Now it's still likely that each ORM will have its own default conventions and that you won't be necessarily be able to persist a class with each and every ORM without doing some changes. Hopefully you won't have to change your code if it could be done by providing some metadata to the ORM that describes your intent (or even some generic rules ?) or you could create your code to be prepared for that (using your own interface that could itself inherit from the particular interface(s) an ORM needs ?)

    At some point, perhaps some organization will try to establish and spread common conventions accross ORMs ?


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
    • Marked as answer by buaaytt Tuesday, June 28, 2011 2:24 AM
    Monday, June 27, 2011 9:48 AM
  • Yep, I guess I had some misunderstandings of the term POCO. I thought the 'plain old' part might indicate that EF could work with any legacy classes. For example, in some legacy project, developers might have their own base Collection interface and have all collection-like classes implement it. In this case, maybe developers will have to do some amount of extra work to have them work with EF.
    You Can't Stop Me!
    Tuesday, June 28, 2011 2:24 AM
  • Ok, this is just that being able to persist a POCO class doesn't mean that all POCO classes can be persisted without any work regardless of its design. If the POCO class doesn't match the ORM conventions you still have to do something (not necessarily modifying the class code but at least explaining the ORM through rules or metadata what are your own conventions).

    I never checked if it made it in final but in the CTP you had for example pluggable convention allowing to change the default convention : http://blogs.msdn.com/b/adonet/archive/2011/01/10/ef-feature-ctp5-pluggable-conventions.aspx

     


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
    Tuesday, June 28, 2011 8:44 AM