locked
dbContext vs ObjectContext issue RRS feed

  • Question

  • Hi

    We have been using EF for a couple of years now and find it works and performs really well using the standard (non-POCO) objectcontext, standard code generation. With the release of the new light-weight dbcontext we have started to look at moving new projects over to this new technology, we will still maintain a database-first model but use the DbContext POCO generator for c#.

    We have hit a bit of a show-stopper, with the ObjectContext, we create a public partial class to match each of the classes generated by EF, this allows us to create constructors for each of our entities from which we are able to set defaults for all properties within the class. This works really well and gets us over the lack of default support with the EF Model Designer (yes I know you can set numeric and string, but your can't do dates, this way we can set property defaults for all properties of an entity in one place. See the code below :-

    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    namespace DataModel
    {
        public partial class ProductGroup
        {
            public ProductGroup()
            {
                _ProductGroupCode = 0;
                _Description = String.Empty;
    
                _HideRecord = false;
                _CreatedBy = Environment.UserName;
                _CreatedOn = DateTime.Now;
                _LastUpdatedBy = Environment.UserName;
                _LastUpdatedOn = DateTime.Now;
                _URNo = 0;
                //_TimeStamp = null;
            }
        }
    }
    

    The problem is, the POCO classes will use a default constructor if it needs to initialize a collection, see below :-

    using System;
    using System.Collections.Generic;
    
    namespace MOPS2012.DataModel
    {
        public partial class ProductGroup
        {
            public ProductGroup()
            {
                this.Products = new HashSet<Product>();
            }
        
            public int ProductGroupCode { get; set; }
            public string Description { get; set; }
            public bool HideRecord { get; set; }
            public string CreatedBy { get; set; }
            public System.DateTime CreatedOn { get; set; }
            public string LastUpdatedBy { get; set; }
            public System.DateTime LastUpdatedOn { get; set; }
            public int URNo { get; set; }
            public byte[] TimeStamp { get; set; }
        
            public virtual ICollection<Product> Products { get; set; }
        }
        
    }

    If we try and create the partial class and the default constructor we get the following compile error.

    Error    1    Type 'MOPS2012.DataModel.ProductGroup' already defines a member called 'ProductGroup' with the same parameter types    C:\TFS2010\Mail Order Processing 2012\MOPS2012.DataModel\_ProductGroup.cs    10    16    MOPS2012.DataModel

    So my question is, how do we duplicate this functionality using dbcontext and poco's ?


    Mark Harby Nottingham, UK

    Thursday, March 29, 2012 4:29 PM

Answers

  • Hi Harby, 

    You could modify the T4 template to include a partial method which will allow you to implement the method in the partial class and perform any initialization you need to there. Modifying the template gave me the following Customer class:

        public partial class Customer
        {
        	partial void Initialize();
        
            public Customer()
            {
                this.CustomerAddresses = new HashSet<CustomerAddress>();
                this.Orders = new HashSet<Order>();
        		Initialize();
            }
        
            public int Id { get; set; }
            public string Name { get; set; }
        
            public virtual ICollection<CustomerAddress> CustomerAddresses { get; set; }
            public virtual ICollection<Order> Orders { get; set; }
        }

    And the initialization logic was inserted in my partial class:

        partial class Customer
        {
            partial void Initialize()
            {
                //set defaults here...
                Name = "-";
            }
        }

    Note that I also removed the if (...) surrounding the default constructor, so all entities will have a default constructor which calls the Initialize() method. I've uploaded the T4 template to my Skydrive here: https://skydrive.live.com/redir.aspx?cid=cb11f0c50e755750&resid=CB11F0C50E755750!7652&parid=CB11F0C50E755750!136

    Regards,

    Tyler

    • Marked as answer by Alan_chen Thursday, April 5, 2012 8:51 AM
    Friday, March 30, 2012 12:37 AM