RSS

Monthly Archives: September 2013

Understanding Previous Co-Workers After You have Left

So today I had an unusual email wait let me start from the beginning. I was at a company for some time and left for a new opportunity I worked with another developer to co-develop two websites with the same supporting back ends. Though we had our differences I always thought we were good associates. At my new place of work I came across a problem and remembered an open source tool that I couldn’t remember the name of so I emailed this previous co-worker wondering if he remembered the name for it and here is the message chain with names redacted and any personally identifiable information:

I just wanted the name of the public library not anything developed by Acme. Thanks for the answer though.

Alex Seabrooks

Senior Application developer *

Phone:  *

Location: *     

From: * [*]
Sent: Tuesday, September 24, 2013 1:58 PM
To: Seabrooks, Alex
Subject: RE: Hi *

Hello Alex,

Sorry, but I did not receive permission to divulge any Acme IP nor the sources used to develop Acme IP.

*name*

From: Seabrooks, Alex [*]
Sent: Monday, September 23, 2013 10:23 AM
To: ******
Subject: Hi *

Hi *****, how have you been? Had a question for you hope you don’t mind me asking you hopefully this email finds you well. A while back we implemented a message pane on the accounts search page that let you know that your last action was successful and you got the library from Google. I have tried finding it and can’t. Do you happen to remember the library address? Working on a similar issue here and would love to find it.

Alex Seabrooks

Senior Application Developer- *

Phone:  *

Location: *     

So I am confused by this but alright this comes down to where you thought you stood and where you stand with previous co-workers.Now asking the name of an open source library to me did not sound like a big deal but from what I can gather he regards it as one or maybe we did not stand where I thought we did when I left. Either way interacting with previous co-workers can sometimes uncover issues you were unaware of and maybe that’s a good thing. I personally wanted to talk about the approach I take as I would have differed in my actions 

Now contracts are a big thing both NDA’s and non-competes, make sure in your contract you are free and clear. NDA means you won’t disclose source code or the like that belongs to your company and sometimes more. So regard your personal agreements first as these override any opinion I have and this is not legal advice. Now with that out of the way, I have some rules in interacting with people I used to work with. My rule of thumb is to be cordial and helpful as the people you work with may work with you again. Nothing creates issues like someone you used to work with coming on board and there being pre-existing issues. This creates unneeded cohesion and work issues. Be nice to previous co-workers who contact you with a minor contact question or the like. Most likely they regard you in a friendly manner. If it’s nothing violating your contracts with said previous company why not help them out. John not remembering that jQuery Validation was the library you used for validation is not a big deal in my opinion and I would gladly help as it is an open source library that was not property of the company we worked for and does not disclose any specific design implementations (I.E. code). But let me get your opinion on this how do you feel should you brick wall or be cordial? Inbox me and I will approve your messages as I receive them as usual.

 

 
Leave a comment

Posted by on September 24, 2013 in Uncategorized

 

Repository and Unit of Work that is Fully Generic Part 3

So now for the last part the extensions to DBContext

using System;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Reflection;

namespace MyCompany.Repo.Generic.Extensions
{
    ///
/// Code First extensions.
    ///
    public static class DbContextExtensions
    {
        ///
/// Adds an entity (if newly created) or update (if has non-default Id).
        ///
        ///
        ///The db context.
        ///The entity.
        ///
        ///
        /// Will not work for HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).
        /// Will not work for composite keys.
        ///
        public static T AddOrUpdate(this DbContext context, T entity)
            where T : class
        {
            if (context == null) throw new ArgumentNullException("context");
            if (entity == null) throw new ArgumentNullException("entity");

            if (IsTransient(context, entity))
            {
                context.Set().Add(entity);
            }
            else
            {
                context.Set().Attach(entity);
                context.Entry(entity).State = EntityState.Modified;
            }
            return entity;
        }

        ///
/// Determines whether the specified entity is newly created (Id not specified).
        ///
        ///
        ///The context.
        ///The entity.
        ///
        ///   true if the specified entity is transient; otherwise, false.
        ///
        ///
        /// Will not work for HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).
        /// Will not work for composite keys.
        ///
        public static bool IsTransient(this DbContext context, T entity)
            where T : class
        {
            if (context == null) throw new ArgumentNullException("context");
            if (entity == null) throw new ArgumentNullException("entity");

            var propertyInfo = FindPrimaryKeyProperty(context);
            var propertyType = propertyInfo.PropertyType;
            //what's the default value for the type?
            var transientValue = propertyType.IsValueType ?
                Activator.CreateInstance(propertyType) : null;
            //is the pk the same as the default value (int == 0, string == null ...)
            return Equals(propertyInfo.GetValue(entity, null), transientValue);
        }

        ///
/// Loads a stub entity (or actual entity if already loaded).
        ///
        ///
        ///The context.
        ///The id.
        ///
        ///
        /// Will not work for composite keys.
        ///
        public static T Load(this DbContext context, object id)
             where T : class
        {
            if (context == null) throw new ArgumentNullException("context");
            if (id == null) throw new ArgumentNullException("id");

            var property = FindPrimaryKeyProperty(context);
            //check to see if it's already loaded (slow if large numbers loaded)
            var entity = context.Set().Local
                .FirstOrDefault(x => id.Equals(property.GetValue(x, null)));
            if (entity == null)
            {
                //it's not loaded, just create a stub with only primary key set
                entity = CreateEntity(id, property);

                context.Set().Attach(entity);
            }
            return entity;
        }

        ///
/// Determines whether the specified entity is loaded from the database.
        ///
        ///
        ///The context.
        ///The id.
        ///
        ///   true if the specified entity is loaded; otherwise, false.
        ///
        ///
        /// Will not work for composite keys.
        ///
        public static bool IsLoaded(this DbContext context, object id)
            where T : class
        {
            if (context == null) throw new ArgumentNullException("context");
            if (id == null) throw new ArgumentNullException("id");

            var property = FindPrimaryKeyProperty(context);
            //check to see if it's already loaded (slow if large numbers loaded)
            var entity = context.Set().Local
                .FirstOrDefault(x => id.Equals(property.GetValue(x, null)));
            return entity != null;
        }

        ///
/// Marks the reference navigation properties unchanged.
        /// Use when adding a new entity whose references are known to be unchanged.
        ///
        ///
        ///The context.
        ///The entity.
        public static void MarkReferencesUnchanged(DbContext context, T entity)
            where T : class
        {
            var objectContext = ((IObjectContextAdapter)context).ObjectContext;
            var objectSet = objectContext.CreateObjectSet();
            var elementType = objectSet.EntitySet.ElementType;
            var navigationProperties = elementType.NavigationProperties;
            //the references
            var references = from navigationProperty in navigationProperties
                             let end = navigationProperty.ToEndMember
                             where end.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne ||
                             end.RelationshipMultiplicity == RelationshipMultiplicity.One
                             select navigationProperty.Name;
            //Note: We don't check Collections. EF wants to handle the object graph so we let it.

            var parentEntityState = context.Entry(entity).State;
            foreach (var navigationProperty in references)
            {
                //if it's modified but not loaded, don't need to touch it
                if (parentEntityState == EntityState.Modified &&
                    !context.Entry(entity).Reference(navigationProperty).IsLoaded)
                    continue;
                var propertyInfo = typeof(T).GetProperty(navigationProperty);
                var value = propertyInfo.GetValue(entity, null);
                context.Entry(value).State = EntityState.Unchanged;
            }
        }

        private static PropertyInfo FindPrimaryKeyProperty(IObjectContextAdapter context)
            where T : class
        {
            //find the primary key
            var objectContext = context.ObjectContext;
            //this will error if it's not a mapped entity
            var objectSet = objectContext.CreateObjectSet();
            var elementType = objectSet.EntitySet.ElementType;
            var pk = elementType.KeyMembers.First();
            //look it up on the entity
            var propertyInfo = typeof(T).GetProperty(pk.Name);
            return propertyInfo;
        }

        private static T CreateEntity(object id, PropertyInfo property)
            where T : class
        {
            // consider IoC here
            var entity = (T)Activator.CreateInstance(typeof(T));
            //set the value of the primary key (may error if wrong type)
            property.SetValue(entity, id, null);
            return entity;
        }
    }
}

  1. Create an Entity project
  2. Add EF 5 from nugget
  3. Add an ADO.Net Entity Data Model of your database
  4. Right click on the designer and click “Add Code Generation Item”
  5. If you do not have the EF 5.x DbContect Generator installed already click online templates select the EF 5.x DbContect Generator, name it appropriately, and click add.
  6. If they do not generat off the bat open the .tt and put in the correct .edmx file name and your db context and poco classes will generate
  7. Add the connection string into the consuming app and add your entity project and the generic repo to your consuming app. Then do something like this in you BLL J
            NPM_EXTEntities context = new NPM_EXTEntities();
            IUnitOfWork efu = new UoWFactory(context).getUoW();

            IGenericRepository<Application>; 
            applications = efu.GetRepository<Application>;
 
Leave a comment

Posted by on September 4, 2013 in C#, Entity Framework, Repository, SQL, Unit Of Work

 

Tags: , , , , , ,

Repository and Unit of Work that is Fully Generic Part 2

So now we continue with the Unit Of Work Factory and the EF specific Items along with Extensions to the DB Context

UoWFactory

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;

namespace MyCompany.Repo.Generic
{
    public class UoWFactory : IDisposable
    {
        #region Variables
        private readonly string _context;
        private readonly DbContext _DBcontext;
        #endregion

        #region Constructor(s)
        public UoWFactory(string context)
        {
            _context = context;
        }

        public UoWFactory(DbContext context)
        {
            _DBcontext = context;
        }
        #endregion

        #region Public Methods
        public IUnitOfWork GetUoW()
        {
            if (_DBcontext != null)
            {
                return new EFUnitOfWork( _DBcontext);
            }
            else
            {
                /*this will be the EL unit of work which needs to be fleshed out to 
                 * process the LINQ expressions for the IQueryable's and the like 
                 * this was beyond the scope of what I was asked to do for my project
                 * and will need to be finalized at a later time unless I have to convert from EF to EL
                 */                
               throw new NotImplementedException("EL Unit Of Work is currently unavailable");
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        #region Protected and Private Methods
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
                if (_DBcontext != null)
                    _DBcontext.Dispose();
        }
        ~UoWFactory()
        {
            Dispose(false);
        }
        #endregion

    }
}

EFRepository

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Entity;
using System.Data;
using MyCompany.Repo.Generic.Extensions;

namespace MyCompany.Repo.Generic
{
    public class EFRepository<T> : BaseGenericRepository, IGenericRepository<T> where T : class
    {
        #region Variables
        private readonly DbContext _context;
        #endregion

        #region Constructor(s)
        public EFRepository(DbContext context)
        {
            _context = context;
        }
        #endregion

        #region Public Methods

        public override Type Type
        {
            get { return typeof(T); }
        }

        public T Value { get; set; }
 
        public IQueryable<T> Get
        {
            get { return _context.Set<T>(); }
        }
 
        public IQueryable<T> GetIncluding(params Expression<Func<T, object>>[] includeProperties)
        {
            IQueryable<T> query = _context.Set<T>();
            foreach (var includeProperty in includeProperties)
            {
                query = query.Include(includeProperty);
            }
            return query;
        }
 
        public T Find(object[] keyValues)
        {
            return _context.Set<T>().Find(keyValues);
        }
 
        public void Add(T entity)
        {
            _context.Set<T>().Add(entity);
        }
 
        public void Update(T entity)
        {
            var entry = _context.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                _context.Set<T>().Attach(entity);
                entry = _context.Entry(entity);
            }
            entry.State = EntityState.Modified;
        }
 
        public void AddOrUpdate(T entity)
        {
            //uses DbContextExtensions to check value of primary key
            _context.AddOrUpdate(entity);
        }
 
        public void Delete(object[] keyValues)
        {
            //uses DbContextExtensions to attach a stub (or the actual entity if loaded)
            var stub = _context.Load<T>(keyValues);
            _context.Set<T>().Remove(stub);
        }
        
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        #region Protected and Private Methods
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
                if (_context != null)
                    _context.Dispose();
        }

        ~EFRepository()
        {
            Dispose(false);
        }
        #endregion

    }
}

EFUnitOfWork

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.Data;

namespace MyCompany.Repo.Generic
{
    public class EFUnitOfWork : IUnitOfWork
    {
        #region Variables
        private readonly DbContext context;
        private readonly Dictionary<Type, BaseGenericRepository> _dictionary;
        #endregion

        #region Constructor(s)
        public EFUnitOfWork(DbContext context)
        {
            this.context = context;
            this.context.ChangeTracker.DetectChanges();
            this.context.Configuration.AutoDetectChangesEnabled = true;
            _dictionary = new Dictionary<Type, BaseGenericRepository>();
        }
        #endregion

        #region Repository Collection Methods
        
            private void Put<T>(EFRepository<T> item) where T : class
            {
                _dictionary[typeof(T)] = item;
            }

            private EFRepository<T> Get<T>() where T : class
            {
                if (_dictionary.ContainsKey(typeof(T)))
                {
                    return _dictionary[typeof(T)] as EFRepository<T>;
                }
                else
                {                    
                    EFRepository<T> efr = new EFRepository<T>(context);
                    Put<T>(efr);
                    return efr;
                }                
            }

        #endregion

        #region Public Methods


        public IGenericRepository<T> GetRepository<T>() where T : class
        {            
            return Get<T>();
        }

        public void SaveChanges()
        {
            context.SaveChanges();
        }

        public void RollBack()
        {
            //detect all changes (probably not required if AutoDetectChanges is set to true)
            context.ChangeTracker.DetectChanges();

            //get all entries that are changed
            var entries = context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged).ToList();

            //try to discard changes on every entry
            foreach (var dbEntityEntry in entries)
            {
                var entity = dbEntityEntry.Entity;

                if (entity == null) continue;

                if (dbEntityEntry.State == EntityState.Added)
                {
                    //if entity is in Added state, remove it. (there will be problems with Set methods if entity is of proxy type, in that case you need entity base type
                    var set = context.Set(entity.GetType());
                    // now lets actually remove it
                    set.Remove(entity);
                }
                else if (dbEntityEntry.State == EntityState.Modified)
                {

                    context.Entry(dbEntityEntry.Entity).CurrentValues.SetValues(context.Entry(dbEntityEntry.Entity).OriginalValues);
                    //may also need to set back to unmodified -
                    //I'm unsure if EF will do this automatically
                    context.Entry(dbEntityEntry.Entity).State = EntityState.Unchanged;                    
                }
                else if (dbEntityEntry.State == EntityState.Deleted)
                    //entity is deleted... change its values back to default and set it to unmodified
                    context.Entry(dbEntityEntry).CurrentValues.SetValues(context.Entry(dbEntityEntry).OriginalValues);
                    dbEntityEntry.State = EntityState.Unchanged;
            }
        }

        public void Dispose()
        {
            context.Dispose();
        }

        #endregion

    }
}

 In part 3 we will show the extension methods for DBContext and go into useage.


 
Leave a comment

Posted by on September 4, 2013 in C#, Entity Framework, Repository, SQL, Unit Of Work

 

Tags: , , , , ,

Repository and Unit of Work that is Fully Generic Part 1

So I have been working on creating a generic repository and unit of work and man there are no full examples out there. The following code I wrote is a combination of mine and other peoples work that I referenced combined into what I like to think is a very strong generic unit of work and repository that does not need to have the repositories declared in the unit of work :). Also on your POCO’s if you want EF to throw conncurency errors for Store Wins instead of Client Wins use the timestamp decorator from System.ComponentModel.DataAnnotations. Here is the code

IUnitOfWork

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCompany.Repo.Generic
{
    public interface IUnitOfWork : IDisposable
    {
        IGenericRepository<T> GetRepository<T>() where T : class;
        void SaveChanges();
        void RollBack();
    }
}

IGenericRepository

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace MyCompany.Repo.Generic
{
    public interface IGenericRepository<T> where T : class
    {
        IQueryable<T> Get { get; }
        IQueryable<T> GetIncluding(params Expression<Func<T, object>>[] includeProperties);
        T Find(object[] keyValues);
        void Add(T entity);
        void Update(T entity);
        void AddOrUpdate(T entity);
        void Delete(object[] keyValues);
    }
}

Base Generic Repository

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCompany.Repo.Generic
{
    /// <summary>
    /// This class is used to allow you to store the repositories in a collection so they stay in scope 
    /// of the unit of work since in .net there is no class<?> like there is in Java
    /// </summary>
    public abstract class BaseGenericRepository
    {
        public abstract Type Type { get; }
    }
}

Ther rest is to come in part 2

 
1 Comment

Posted by on September 4, 2013 in C#, Entity Framework, Repository, SQL, Unit Of Work

 

Tags: , , , , , ,