public TEntity ReadFirstOrDefault(DbDataReader reader)
        {
            using (reader)
            {
                var session = new ReadSession();

                // Read entity
                var entity   = default(TEntity);
                var previous = entity;
                while (reader.Read())
                {
                    previous = entity;
                    entity   = ToEntity(reader, previous, session);
                    if (previous != null && entity != previous)
                    {
                        break;
                    }
                }

                //// Read navigation properties
                //while (reader.NextResult())
                //{
                //    // Find navigation property
                //    var property = Properties.FirstOrDefault(p => p.ForeignTable.HasPrimaryKey(reader));
                //    property.SetProperty(, reader);
                //}

                return(entity);
            }
        }
        public TEntity ToEntity(DbDataReader reader, TEntity previous, ReadSession session, int recursionDepth = 0)
        {
            // If primary key properties is not exists or null return default value
            var primaryKeyIndex = PrimaryKey.GetColumnIndexByAlias(reader);

            if (primaryKeyIndex == null || reader.IsDBNull(primaryKeyIndex.Value))
            {
                return(default(TEntity));
            }

            // Get current entity
            var shift = (primaryKeyIndex.Value - PrimaryKey.Index) ?? 0;

            var isSameEntity = false;

            if (previous != null)
            {
                var prevKey = PrimaryKey.GetField(previous);
                var currKey = PrimaryKey.GetValue(reader, shift);
                isSameEntity = prevKey.Equals(currKey);
            }

            var entity = previous;

            if (!isSameEntity)
            {
                var positions = session.GetColumnPositions(typeof(TEntity), Columns.Count);

                // Set columns
                int idx = 0;
                entity = new TEntity();
                foreach (var column in Columns)
                {
                    var pos = positions[idx++];
                    column.SetField(entity, reader, pos);
                }
            }

            // Set one to one navigation properties
            if (recursionDepth < MaxRecursionDepth)
            {
                foreach (var property in Properties)
                {
                    property.SetProperty(entity, reader, session, recursionDepth);
                }
            }

            return(entity);
        }
        public async Task <TEntity> ReadFirstOrDefaultAsync(DbDataReader reader, CancellationToken?token = null)
        {
            using (reader)
            {
                var session = new ReadSession();

                // Read entity
                var entity   = default(TEntity);
                var previous = entity;
                while (await reader.ReadAsync(token ?? CancellationToken.None))
                {
                    entity = ToEntity(reader, previous = entity, session);
                    if (entity != previous)
                    {
                        break;
                    }
                }

                return(entity);
            }
        }
        public async Task <List <TEntity> > ReadListAsync(DbDataReader reader, CancellationToken?token = null)
        {
            var list = new List <TEntity>();

            using (reader)
            {
                var session = new ReadSession();

                var entity   = default(TEntity);
                var previous = entity;
                while (await reader.ReadAsync(token ?? CancellationToken.None))
                {
                    previous = entity;
                    entity   = ToEntity(reader, previous, session);
                    if (entity != previous)
                    {
                        list.Add(entity);
                    }
                }
            }
            return(list);
        }
        public List <TEntity> ReadList(DbDataReader reader)
        {
            var list = new List <TEntity>();

            using (reader)
            {
                var session = new ReadSession();

                // Read entities
                var entity   = default(TEntity);
                var previous = entity;
                while (reader.Read())
                {
                    entity = ToEntity(reader, previous = entity, session);
                    if (entity != previous)
                    {
                        list.Add(entity);
                    }
                }
            }
            return(list);
        }