views:

83

answers:

1

I'm very new to the Entity Framework and trying to understand how to best architect my data layer in way that makes the most sense from the prospective of a developer. I'm working on a proof of concept using the AventureWorks database. I built a generic repository that I use to query any table in the database. Following is a short, but compilable (I hope), snippet (the actual code has methods to update, delete, etc.):

    /// <summary>
    /// A generic repository for working with data in the database
    /// </summary>
    /// <typeparam name="T">A POCO that represents an Entity Framework entity</typeparam>
    public class DataRepository<T> : IDisposable, IRepository<T> where T : class
    {
        /// <summary>
        /// The context object for the database
        /// </summary>
        private ObjectContext _context;

        /// <summary>
        /// The IObjectSet that represents the current entity. Used to query, add, modify and delete objects of the specified entity.
        /// </summary>
        private IObjectSet<T> _objectSet;

        /// <summary>
        /// Initializes a new instance of the DataRepository class
        /// </summary>
        public DataRepository()
            : this(new AdventureWorksEntities())
        {
        }

        /// <summary>
        /// Initializes a new instance of the DataRepository class
        /// </summary>
        /// <param name="context">The Entity Framework ObjectContext</param>
        public DataRepository(ObjectContext context)
        {
            _context = context;
            _objectSet = _context.CreateObjectSet<T>();
        }

        /// <summary>
        /// Gets all records as an IQueryable
        /// </summary>
        /// <returns>An IQueryable object, containing the results of the query</returns>
        public IQueryable<T> GetQuery()
        {
            return from x in _objectSet select x;
        }

        /// <summary>
        /// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
        /// </summary>
        /// <param name="disposing">A boolean value indicating whether or not to dispose managed resources</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_context != null)
                {
                    _context.Dispose();
                    _context = null;
                }
            }
        }
    }

In my ASP.NET demo app, I can use the repository, as follows, to get an Employee record (notice the reference to Contact):

        using (DataRepository repository = new DataRepository())
        {
            this.GridView1.DataSource = from x in repository.GetQuery()
                                        select new
                                        {
                                            x.MaritalStatus,
                                            x.Contact.FirstName,
                                            x.Contact.LastName,
                                            x.BirthDate
                                        };
            this.GridView1.DataBind();
        }

This could work out well, but my concern is that the View now has knowledge of the database schema, which I don't like. For example, if I were to decide to move the FirstName and LastName columns into the Employee table, I would have to rewrite all lines of code where I referenced the columns as I did in the snippet above. My preference is to change the conceptual model by creating properties off of the Employee class and have Entity Framework automatically perform the JOIN, as necessary.

Firstly, are there any "lessons learned" from anybody that has designed a model like I have proposed? Anything negative that I should look out for? Secondly, are there any alternatives that I should be aware of?

+2  A: 

Part of what you're running up against is ASP.NET. Having the view aware of the repository at all is suspicious. In MVC, for example, binding repository public types to a view model would be done in the controller, and the view would only know about the view model.

But even in straight ASP.NET I'd suggest creating dedicated view/presentation models and projecting onto them using an L2E query, similar to what you're doing now with the anonymous type. Using a presentation model instead of an anonymous type will allow you to move the query out of the Page and remove knowledge of the Entity type from the page.

Craig Stuntz
The final project actually will be MVC. I just threw this into an ASP.NET app so I could quickly bind to a GridView to get the results. In regard to projection, I'm not against this approach (I should have mentioned that in my post). I was just wondering if modifying the conceptual model is going to come back to haunt me, later in life.
senfo