RSS

Category Archives: SQL

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: , , , , , ,

Entity Framework Error 3004

Error 3004: Problem in mapping fragments starting at line <#>: No mapping specified for properties MyEntity.MyValue in Set MyEntities. An Entity with Key (PK) will not round-trip when: Entity is type [MyEntities.MyEntity]

This is a annoying error and the best thing to do is delete the offending table and regenerate the model. Not the greatest answer but when your pressed for time it is what it is.

 
Leave a comment

Posted by on January 2, 2013 in C#, Entity Framework, SQL

 

Tags: , ,

Use “LIKE()” Operation for Entity Frame Work (yes it is possible)

Alright so this is a tie in with the previous post but is still separate. I will get to that in the next post. So linq to entities was nice enough not to give us a true like operator like in linq to sql and if you use the linq to sql it throws a error and does not work against entities. So i needed a way and I found one but catch is it only works out of the box with mssql and for now we will stick with that. Sorry if you use oracle and the like suck to be there at the moment.

So here you go I have created a instance of a ObjectQuery and now I am adding on my filters for final execution and in this one I need to return a name with wild cards in place of spaces and special characters

vb .net

            Dim searchname As String = String.Format("%{0}%", replaceSpecialCharactersWith(TextBoxName.Text, "%"))
            entity = From client In entity.AsQueryable Where System.Data.Objects.SqlClient.SqlFunctions.PatIndex(searchname, client.Name) > 0 

C#

            string searchname = string.Format("%{0}%", replaceSpecialCharactersWith(TextBoxName.Text, "%"));
            entity = from client in entity.AsQueryablewhere System.Data.Objects.SqlClient.SqlFunctions.PatIndex(searchname, client.Name) > 0;

as you can see it uses the patindex function method from sql this along with deffered execution will allow you to do likes and then combine with the Or operator and you are good to go. Looking at the trace also it only tacked on a where calling the function so not much of a performance hit eithier. So using the code method below and this = automatic like on full name fields from a single textbox search :).

 
Leave a comment

Posted by on July 9, 2012 in C#, Entity Framework, SQL

 

Tags: , , ,

Convert LINQ to Entity ObjectQuery to DataTable

It has been a while, I know and I have been meaning to blog but have been uber busy so here is a new one for you.
So for anyone who has used LINQ to DataSet you know there is a method for CopyToDataTable(). For LINQ to Entity there is no such thing and though I will not go into why there are reasons and they make partial sense but I needed to do this to get better control of my data binding. So I went out and used reflection and came back with a simple way to convert the returned IEnumerable object list to a DataTable this treats each object in the returned entity as a DataRow and dynamically gets the properties and the column names. Below are the C# and VB.Net versions. Also make sure to include the System.Reflection Library in your class where you use this.

    Public Function ObjectQueryToDataTable(Of T)(objlist As IEnumerable(Of T)) As DataTable
        Dim dtReturn As New DataTable()

        Dim objProps As PropertyInfo() = Nothing

        If objlist Is Nothing Then
            Return dtReturn
        End If

        For Each objRec As T In objlist
            If objProps Is Nothing Then
                objProps = DirectCast(objRec.[GetType](), Type).GetProperties()
                For Each objpi As PropertyInfo In objProps
                    Dim colType As Type = objpi.PropertyType

                    If (colType.IsGenericType) AndAlso (colType.GetGenericTypeDefinition() = GetType(Nullable(Of ))) Then
                        colType = colType.GetGenericArguments()(0)
                    End If

                    dtReturn.Columns.Add(New DataColumn(objpi.Name, colType))
                Next
            End If

            Dim dr As DataRow = dtReturn.NewRow()

            For Each pi As PropertyInfo In objProps
                dr(pi.Name) = If(pi.GetValue(objRec, Nothing) Is Nothing, DBNull.Value, pi.GetValue(objRec, Nothing))
            Next

            dtReturn.Rows.Add(dr)
        Next
        Return dtReturn
    End Function
public DataTable ObjectQueryToDataTable<T>(IEnumerable<T> objlist)
{
	DataTable dtReturn = new DataTable();

	PropertyInfo[] objProps = null;

	if (objlist == null) {
		return dtReturn;
	}

	foreach (T objRec in objlist) {
		if (objProps == null) {
			objProps = ((Type)objRec.GetType()).GetProperties();
			foreach (PropertyInfo objpi in objProps) {
				Type colType = objpi.PropertyType;

				if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>))) {
					colType = colType.GetGenericArguments()(0);
				}

				dtReturn.Columns.Add(new DataColumn(objpi.Name, colType));
			}
		}

		DataRow dr = dtReturn.NewRow();

		foreach (PropertyInfo pi in objProps) {
			dr(pi.Name) = pi.GetValue(objRec, null) == null ? DBNull.Value : pi.GetValue(objRec, null);
		}

		dtReturn.Rows.Add(dr);
	}
	return dtReturn;
}

Hope this helps you out as always if you have a better way let me know :).

 
2 Comments

Posted by on July 6, 2012 in ASP.Net, C#, Entity Framework, SQL

 

Tags: , , ,

Adding multiple parameters all at once to a SqlCommand using AddRange

So rarely does a Stored Procedure take just one argument and well typing the same thing over and over and over can be a pain so what to do? use AddRange and create a array of sql command using simple syntax and copy pasta

 using (SqlCommand cmd = new SqlCommand() { CommandType = CommandType.StoredProcedure, Connection = connString, CommandText = "Exec Card_Add_Company" })
{
cmd.Parameters.AddRange(new SqlParameter[]
{
new SqlParameter("@Example",NewExampleInfo.Rows[0]["CompanyName"].ToString()),
new SqlParameter("@Example_Contact",NewExampleInfo.Rows[0]["Name"].ToString()),
new SqlParameter("",[ControlNameHere]),
new SqlParameter("",[ControlNameHere])
})

Using this then filling in the blanks can save you quite a bit of time and you get those 13-20 something variables out of the way in no time for me it was only nine so i made 9 SqlParameters in the add range statement and bam love is in the air. Make a custom snippet for this to use with intelisense and you are golden.

 
Leave a comment

Posted by on February 28, 2012 in C#, SQL