-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
(queryContext, dataReader, resultContext, resultCoordinator) =>
{
resultContext.Values == null ?
{
Customer namelessParameter{0};
namelessParameter{0} =
{
MaterializationContext materializationContext1;
IEntityType entityType1;
Customer instance1;
InternalEntityEntry entry1;
bool hasNullKey1;
materializationContext1 = new MaterializationContext(
ValueBuffer,
queryContext.Context
);
instance1 = null;
entry1 = queryContext.TryGetEntry(
key: Key: Customer.CustomerID PK,
keyValues: new object[]{ try { (object)dataReader.GetString(0) } catch (Exception) { ... } },
throwOnNullKey: True,
hasNullKey: hasNullKey1);
!(hasNullKey1) ? entry1 != default(InternalEntityEntry) ?
{
entityType1 = entry1.EntityType;
return instance1 = (Customer)entry1.Entity;
} :
{
ValueBuffer shadowValueBuffer1;
shadowValueBuffer1 = ValueBuffer;
entityType1 = EntityType: Customer;
instance1 = switch (entityType1)
{
case EntityType: Customer:
{
return
{
Customer instance;
instance = new Customer(
materializationContext1.Context,
InfrastructureExtensions.GetService<ILazyLoader>((IInfrastructure<IServiceProvider>)materializationContext1.Context),
try { dataReader.GetString(0) } catch (Exception) { ... }
);
instance.Context = (materializationContext1.Context as NorthwindContext);
instance.<Address>k__BackingField = dataReader.IsDBNull(1) ? default(string) : try { dataReader.GetString(1) } catch (Exception) { ... } ;
instance.<City>k__BackingField = dataReader.IsDBNull(2) ? default(string) : try { dataReader.GetString(2) } catch (Exception) { ... } ;
instance.<CompanyName>k__BackingField = dataReader.IsDBNull(3) ? default(string) : try { dataReader.GetString(3) } catch (Exception) { ... } ;
instance.<ContactName>k__BackingField = dataReader.IsDBNull(4) ? default(string) : try { dataReader.GetString(4) } catch (Exception) { ... } ;
instance.<ContactTitle>k__BackingField = dataReader.IsDBNull(5) ? default(string) : try { dataReader.GetString(5) } catch (Exception) { ... } ;
instance.<Country>k__BackingField = dataReader.IsDBNull(6) ? default(string) : try { dataReader.GetString(6) } catch (Exception) { ... } ;
instance.<Fax>k__BackingField = dataReader.IsDBNull(7) ? default(string) : try { dataReader.GetString(7) } catch (Exception) { ... } ;
instance.<Phone>k__BackingField = dataReader.IsDBNull(8) ? default(string) : try { dataReader.GetString(8) } catch (Exception) { ... } ;
instance.<PostalCode>k__BackingField = dataReader.IsDBNull(9) ? default(string) : try { dataReader.GetString(9) } catch (Exception) { ... } ;
instance.<Region>k__BackingField = dataReader.IsDBNull(10) ? default(string) : try { dataReader.GetString(10) } catch (Exception) { ... } ;
return instance;
};
}
default:
null
}
;
entry1 = entityType1 == default(IEntityType) ? default(InternalEntityEntry) : queryContext.StartTracking(
entityType: entityType1,
entity: instance1,
valueBuffer: shadowValueBuffer1);
return instance1;
} : default(void);
return instance1;
};
resultContext.Values = new object[]{ namelessParameter{0} };
return ShaperProcessingExpressionVisitor.InitializeIncludeCollection<Customer, Customer>(
collectionId: 0,
queryContext: queryContext,
dbDataReader: dataReader,
resultCoordinator: resultCoordinator,
entity: (Customer)(resultContext.Values[0]),
parentIdentifier: Func<QueryContext, DbDataReader, object[]>,
outerIdentifier: Func<QueryContext, DbDataReader, object[]>,
navigation: Navigation: Customer.Orders (List<Order>) Collection ToDependent Order Inverse: Customer PropertyAccessMode.Field,
clrCollectionAccessor: ClrICollectionAccessor<Customer, List<Order>, Order>,
trackingQuery: True);
} : default(void);
ShaperProcessingExpressionVisitor.PopulateIncludeCollection<Customer, Order>(
collectionId: 0,
queryContext: queryContext,
dbDataReader: dataReader,
resultCoordinator: resultCoordinator,
parentIdentifier: Func<QueryContext, DbDataReader, object[]>,
outerIdentifier: Func<QueryContext, DbDataReader, object[]>,
selfIdentifier: Func<QueryContext, DbDataReader, object[]>,
parentIdentifierValueComparers: List<ValueComparer> { DefaultValueComparer<string>, },
outerIdentifierValueComparers: List<ValueComparer> { DefaultValueComparer<string>, },
selfIdentifierValueComparers: List<ValueComparer> { DefaultValueComparer<int>, },
innerShaper: Func<QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator, Order>,
inverseNavigation: Navigation: Order.Customer (Customer) ToPrincipal Customer Inverse: Orders,
fixup: Action<Customer, Order>,
trackingQuery: True);
return IsTrue(resultCoordinator.ResultReady)
? (Customer)(resultContext.Values[0]) : default(Customer);
}
Above is the form of shaper generated in relational when there are collections to be materialized in projection. This is true for both single/split query mode.
Main thing is we cannot call into client code for final result shape till collections are populated fully.
In single query, since there is one spot enumerating over DbReader, we need to store temp values from current row since by the time collection is fully populated the parent would have moved to next row.
In split query mode, since collection elements could depend on parent, we need to generate parent entities before we can call into collection populating code.
Due to above we use ResultContext.Values which is object[] to store temp values we read from database which could be either entities or scalar read directly. This means that if we read some struct value from database then we are boxing it for temporary storage.
We can potentially utilize an actual class with generics to avoid boxing.