We're updating the issue view to help you get more done. 

Refactor DomainObjectQueryGenerator to return executable queries

Description

  • Add two methods to IDomainObjectQueryGenerator:

    • IExecutableQuery<T> CreateScalarQuery<T> (string id, StorageProviderDefinition storageProviderDefinition, QueryModel queryModel)

    • IExecutableQuery<IEnumerable<T>> CreateSequenceQuery<IEnumerable<T>> (string id, ClassDefinition classDefinition, QueryModel queryModel, IEnumerable<FetchQueryModelBuilder> fetchQueryModelBuilders, QueryType queryType)

  • In DomainObjectQueryGenerator, implement CreateScalarQuery the same way as the existing CreateQuery method, but:

    • do not call CheckQueryKind,

    • use QueryType.Scalar,

    • do not call CreateEagerFetchQueries, and

    • wrap the result into a ScalarQueryAdapter<T>; for the result conversion delegate inject an IStorageTypeInformationProvider into the DomainObjectQueryGenerator and get an IStorageTypeInformation for typeof (T), then create a delegate using "ConvertFromStorageType" to convert the database value into the desired type.

      • If the provider cannot return an IStorageTypeInformation for the given type, throw a NotSupportedException with an explanatory exception message.

  • Add a class QueryResultRowAdapter that takes an IQueryResultRow and implements IDatabaseResultRow by delegating to that object.

    • For GetValue<T>, call queryResultRow.GetConvertedValue<T>, get the position from the ColumnID.

    • For GetEntity<T>, throw a NotSupportedException:
      {pre}
      This LINQ provider does not support queries with complex projections that include DomainObjects.
      Either change the query to return just a sequence of DomainObjects ("from o in QueryFactory.CreateLinqQuery<Order>() select o") or change the complex projection to contain no DomainObjects ("from o in QueryFactory.CreateLinqQuery<Order>() select new { o.OrderNumber, o.OrderDate }").
      {pre}

  • Implement CreateSequenceQuery the same way as the existing CreateQuery method, but:

    • do not call CheckQueryKind,

    • if sqlQuery.Kind is EntityQuery, use QueryType.Collection and wrap the result into a DomainObjectSequenceQueryAdapter<T>,

    • otherwise, use QueryType.Custom and wrap the result into a CustomSequenceQueryAdapter<T>; for the result conversion delegate, use the following:

      • call sqlQuery.SqlCommand.GetInMemoryProjection<T> and compile the result to get a Func<IDatabaseResultRow, T> representing the in-memory projection of the custom query,

      • create a Func<IQueryResultRow, T> that uses a QueryResultRowAdapter to call the in-memory projection.

Assignee

Fabian Schmied

Reporter

Fabian Schmied

Labels

None

Time tracking

3h

Components

Fix versions

Priority

Normal
Configure