/// <summary>
        /// Cria um record a partir de um valor.
        /// </summary>
        /// <param name="cache">Instancia do cache onde está os dados.</param>
        /// <param name="key">Chave da entrada do cache.</param>
        /// <param name="descriptor">Descritor do resultado.</param>
        /// <param name="info"></param>
        /// <returns></returns>
        internal static Record CreateRecord(Cache cache, object key, ref Record.RecordDescriptor descriptor, QueryInfo info)
        {
            var resultValue = cache[key];

            if (resultValue is UserBinaryObject)
            {
                var binaryObject = (UserBinaryObject)resultValue;
                using (var ms = new System.IO.MemoryStream(binaryObject.GetFullObject(), false))
                    resultValue = Colosoft.Serialization.Formatters.CompactBinaryFormatter.Deserialize(ms, cache.Name);
            }
            if (resultValue is ICacheItemRecord)
            {
                var itemRecord = (ICacheItemRecord)resultValue;
                if (descriptor.Count == 0)
                {
                    if (info != null && info.Projection != null)
                    {
                        descriptor = new Record.RecordDescriptor();
                        foreach (var field in itemRecord.Descriptor)
                        {
                            if (info.Projection.Any(p => {
                                var column = p.GetColumnInfo();
                                return(column != null && column.Name == field.Name);
                            }))
                            {
                                descriptor.Add(field);
                            }
                        }
                    }
                    else
                    {
                        descriptor = itemRecord.Descriptor;
                    }
                }
                object[] values = new object[descriptor.Count];
                for (int i = 0; i < descriptor.Count; i++)
                {
                    values[i] = itemRecord.GetValue(descriptor[i].Name);
                }
                return(descriptor.CreateRecord(values));
            }
            else
            {
                var propertyInfos = resultValue.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(f => f.Name).ToArray();
                if (descriptor.Count == 0)
                {
                    List <Record.Field> fields = new List <Record.Field>();
                    for (int i = 0; i < propertyInfos.Length; i++)
                    {
                        fields.Add(new Record.Field(propertyInfos[i].Name, propertyInfos[i].ReflectedType));
                    }
                    descriptor = new Record.RecordDescriptor("descriptor", fields);
                }
                object[] values = new object[descriptor.Count];
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = propertyInfos[i].GetValue(resultValue, null);
                }
                return(descriptor.CreateRecord(values));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Cria um registro com base nas chaves do resultado da consulta.
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="keys"></param>
        /// <returns></returns>
        private Record CreateRecord(EntityInfo[] entities, object[] keys)
        {
            var entries = new object[entities.Length];

            for (var i = 0; i < keys.Length; i++)
            {
                if (keys[i] != null)
                {
                    var entry = _cache[keys[i]];
                    if (entry is UserBinaryObject)
                    {
                        var binaryObject = (UserBinaryObject)entry;
                        using (var ms = new System.IO.MemoryStream(binaryObject.GetFullObject(), false))
                            entry = Colosoft.Serialization.Formatters.CompactBinaryFormatter.Deserialize(ms, _cache.Name);
                    }
                    entries[i] = entry;
                }
            }
            PropertyInfo[][] propertyInfos = null;
            if (_descriptor == null)
            {
                var descriptor = new Record.RecordDescriptor();
                _projectionPositions = new List <KeyValuePair <int, string> >();
                if (_query == null || _query.Projection == null || _query.Projection.Count == 0)
                {
                    var entitiesIndex = new List <int>();
                    if (_query != null)
                    {
                        foreach (var info in _query.Entities)
                        {
                            var index = Array.FindIndex(entities, f => !string.IsNullOrEmpty(f.Alias) ? f.Alias == info.Alias : f.FullName == info.FullName);
                            if (index >= 0)
                            {
                                entitiesIndex.Add(index);
                            }
                        }
                    }
                    else
                    {
                        for (var i = 0; i < entities.Length; i++)
                        {
                            entitiesIndex.Add(i);
                        }
                    }
                    foreach (var i in entitiesIndex)
                    {
                        var typeMetadata = GetTypeMetadata(entities[i]);
                        if (typeMetadata == null)
                        {
                            throw new InvalidOperationException(string.Format("Not found TypeMetadata for entity '{0}'", entities[i]));
                        }
                        foreach (var property in typeMetadata)
                        {
                            var index = 0;
                            while (descriptor.Contains(property.Name + (index > 0 ? index.ToString() : "")))
                            {
                                index++;
                            }
                            descriptor.Add(new Record.Field(property.Name + (index > 0 ? index.ToString() : ""), Type.GetType(property.PropertyType, true)));
                            _projectionPositions.Add(new KeyValuePair <int, string>(i, property.Name));
                        }
                        if (typeMetadata.IsVersioned && !descriptor.Contains("RowVersion"))
                        {
                            descriptor.Add(new Record.Field("RowVersion", typeof(long)));
                            _projectionPositions.Add(new KeyValuePair <int, string>(i, "RowVersion"));
                        }
                    }
                }
                else
                {
                    var typeMetadatas = new Dictionary <int, ITypeMetadata>();
                    foreach (var projectionEntry in _query.Projection)
                    {
                        var columnInfo = projectionEntry.GetColumnInfo();
                        if (columnInfo == null)
                        {
                            continue;
                        }
                        var entityInfo = _query.Entities.Where(f => f.Alias == columnInfo.Owner).FirstOrDefault();
                        if (entityInfo == null)
                        {
                            entityInfo = _query.Entities.FirstOrDefault();
                        }
                        var entityIndex = -1;
                        for (var i = 0; i < entities.Length; i++)
                        {
                            if (EntityInfoAliasComparer.Instance.Equals(entities[i], entityInfo))
                            {
                                entityIndex = i;
                                break;
                            }
                        }
                        var name  = columnInfo.Alias ?? columnInfo.Name;
                        var index = 0;
                        while (descriptor.Contains(name + (index > 0 ? index.ToString() : "")))
                        {
                            index++;
                        }
                        if (index > 0)
                        {
                            name += index.ToString();
                        }
                        if (entityIndex < 0)
                        {
                            descriptor.Add(new Record.Field(name, typeof(string)));
                            _projectionPositions.Add(new KeyValuePair <int, string>(-1, null));
                            continue;
                        }
                        ITypeMetadata typeMetadata = null;
                        if (!typeMetadatas.TryGetValue(entityIndex, out typeMetadata))
                        {
                            typeMetadata = GetTypeMetadata(entities[entityIndex]);
                            if (typeMetadata == null)
                            {
                                throw new InvalidOperationException(string.Format("Not found TypeMetadata for entity '{0}'", entities[entityIndex]));
                            }
                            typeMetadatas.Add(entityIndex, typeMetadata);
                        }
                        if (columnInfo.Name == "TableId")
                        {
                            var identityProperty = typeMetadata.GetKeyProperties().FirstOrDefault();
                            if (identityProperty != null)
                            {
                                descriptor.Add(new Record.Field(name, Type.GetType(identityProperty.PropertyType)));
                                _projectionPositions.Add(new KeyValuePair <int, string>(entityIndex, identityProperty.Name));
                            }
                        }
                        else if (columnInfo.Name == Colosoft.Query.DataAccessConstants.RowVersionPropertyName && typeMetadata.IsVersioned)
                        {
                            descriptor.Add(new Record.Field(name, typeof(long)));
                            _projectionPositions.Add(new KeyValuePair <int, string>(entityIndex, Colosoft.Query.DataAccessConstants.RowVersionPropertyName));
                            break;
                        }
                        else
                        {
                            foreach (var property in typeMetadata)
                            {
                                if (property.Name == columnInfo.Name)
                                {
                                    descriptor.Add(new Record.Field(name, Type.GetType(property.PropertyType)));
                                    _projectionPositions.Add(new KeyValuePair <int, string>(entityIndex, property.Name));
                                    break;
                                }
                            }
                        }
                    }
                }
                _descriptor = descriptor;
            }
            object[] values = new object[_descriptor.Count];
            for (var projIndex = 0; projIndex < _projectionPositions.Count; projIndex++)
            {
                var projPosition = _projectionPositions[projIndex];
                if (projPosition.Key < 0)
                {
                    continue;
                }
                var entry = entries[projPosition.Key];
                if (entry == null)
                {
                    continue;
                }
                if (entry is ICacheItemRecord)
                {
                    var itemRecord = (ICacheItemRecord)entry;
                    if (itemRecord.Descriptor.Contains(projPosition.Value))
                    {
                        values[projIndex] = itemRecord.GetValue(projPosition.Value);
                    }
                }
                else
                {
                    if (propertyInfos == null)
                    {
                        propertyInfos = new PropertyInfo[entries.Length][];
                    }
                    if (propertyInfos[projPosition.Key] == null && entry != null)
                    {
                        propertyInfos[projPosition.Key] = entry.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(f => f.Name).ToArray();
                    }
                    if (entry != null)
                    {
                        var propertyInfo = propertyInfos[projPosition.Key].Where(f => f.Name == projPosition.Value).FirstOrDefault();
                        if (propertyInfo != null)
                        {
                            values[projIndex] = propertyInfo.GetValue(entry, null);
                        }
                    }
                }
            }
            return(_descriptor.CreateRecord(values));
        }
        public IQueryResult Execute(QueryInfo query)
        {
            query.Require("query").NotNull();
                        #if DEBUG
            var queryText     = query.ToString().Replace("\r\n", " ");
            var executeNumber = _executeCount++;

            var stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();
#endif
            try
            {
                var cacheResult = ExecuteInCache(query);
                Record.RecordDescriptor descriptor = new Record.RecordDescriptor();
                if (query.Projection != null && query.Projection.Count == 1 && IsCountFunction(query.Projection[0]))
                {
                    var projectionColumn = query.Projection[0];
                    descriptor.Add(new Record.Field(projectionColumn.Alias, typeof(int)));
                    return(new QueryResult(descriptor, new Record[] {
                        descriptor.CreateRecord(new object[] {
                            cacheResult.SearchKeysResult.Count
                        })
                    }, query, Execute));
                }
                var records = new List <Record>();
                IComparer <Record> comparer = null;
                var comparerInitialized     = false;
                using (var recordsEnumerator = new QueryResultSetRecordEnumerator(this._typeSchema, this.Cache, cacheResult, query))
                {
                    while (recordsEnumerator.MoveNext())
                    {
                        var record = recordsEnumerator.Current;
                        descriptor = recordsEnumerator.Descriptor;
                        if (!comparerInitialized && query.Sort != null)
                        {
                            comparerInitialized = true;
                            comparer            = CreateSortComparer(query, descriptor);
                        }
                        if (comparerInitialized)
                        {
                            var index = records.BinarySearch(record, comparer);
                            if (index < 0)
                            {
                                index = ~index;
                            }
                            records.Insert(index, record);
                        }
                        else
                        {
                            records.Add(record);
                        }
                    }
                }
                return(new QueryResult(descriptor, new RecordsResult(records), query, Execute));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                                #if DEBUG
                stopwatch.Stop();
                RegisterEndExecute(stopwatch, queryText, executeNumber);
#endif
            }
        }