예제 #1
0
        protected override Expression VisitStructureExpression(StructureExpression expression)
        {
            var tupleExpression = GetTupleExpression(expression);

            var typeInfo       = expression.PersistentType;
            var tuplePrototype = typeInfo.TuplePrototype;
            var mappingInfo    = expression.Fields
                                 .OfType <FieldExpression>()
                                 .Where(f => f.ExtendedType == ExtendedExpressionType.Field)
                                 .OrderBy(f => f.Field.MappingInfo.Offset)
                                 .Select(f => new Pair <int>(f.Field.MappingInfo.Offset, f.Mapping.Offset))
                                 .Distinct()
                                 .ToArray();

            int[] columnMap = MaterializationHelper.CreateSingleSourceMap(tuplePrototype.Count, mappingInfo);

            var persistentTupleExpression = (Expression)Expression.Call(
                BuildPersistentTupleMethod,
                tupleExpression,
                Expression.Constant(tuplePrototype),
                Expression.Constant(columnMap));

            return(Expression.Convert(
                       Expression.Call(
                           WellKnownMembers.CreateStructure,
                           Expression.Field(itemMaterializationContextParameter, ItemMaterializationContext.SessionFieldInfo),
                           Expression.Constant(expression.Type),
                           persistentTupleExpression),
                       expression.Type));
        }
        public TypeMapping GetTypeMapping(int entityIndex, TypeInfo approximateType, int typeId, Pair <int>[] columns)
        {
            TypeMapping result;
            var         cache = entityMappings[entityIndex];

            if (cache.SingleItem != null)
            {
                if (typeId != ResolveTypeToNodeSpecificTypeIdentifier(cache.SingleItem.Type))
                {
                    throw new ArgumentOutOfRangeException("typeId");
                }
                return(cache.SingleItem);
            }
            if (cache.Items.TryGetValue(typeId, out result))
            {
                return(result);
            }

            var type       = TypeIdRegistry[typeId];
            var keyInfo    = type.Key;
            var descriptor = type.TupleDescriptor;

            var typeColumnMap = columns.ToArray();

            if (approximateType.IsInterface)
            {
                // fixup target index
                for (int i = 0; i < columns.Length; i++)
                {
                    var pair = typeColumnMap[i];
                    var approxTargetIndex = pair.First;
                    var interfaceField    = approximateType.Columns[approxTargetIndex].Field;
                    var field             = type.FieldMap[interfaceField];
                    var targetIndex       = field.MappingInfo.Offset;
                    typeColumnMap[i] = new Pair <int>(targetIndex, pair.Second);
                }
            }

            int[] allIndexes = MaterializationHelper.CreateSingleSourceMap(descriptor.Count, typeColumnMap);
            int[] keyIndexes = allIndexes.Take(keyInfo.TupleDescriptor.Count).ToArray();

            var transform    = new MapTransform(true, descriptor, allIndexes);
            var keyTransform = new MapTransform(true, keyInfo.TupleDescriptor, keyIndexes);

            result = new TypeMapping(type, keyTransform, transform, keyIndexes);

            if (type.Hierarchy.Root.IsLeaf && approximateType == type)
            {
                cache.SingleItem = result;
            }
            else
            {
                cache.Items.Add(typeId, result);
            }
            entityMappings[entityIndex] = cache;

            return(result);
        }