/// <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)); } }
/// <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 } }