question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mapping raw query to entities

See original GitHub issue

Issue type:

[ ] bug report [x] feature request [ ] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [ ] mysql / mariadb [ ] oracle [x] postgres [ ] cockroachdb [ ] sqlite [ ] sqljs [ ] react-native [ ] expo

TypeORM version:

[ ] latest [x] @next [ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

Hello, I’ve been using typeorm for a while and I like it a lot, working with entities adds a lot of convenience.
I use a transformer on my entity classes to conveniently map values when reading/writing from the DB, however this only works if entities are obtained from the query builder or entity manager.

Right now there is no way to simply map a raw query to entities, however sometimes raw queries are a valuable escape hatch that will always be required in some cases, some being more common than others.
Right now I need the UNION operator which is fairly commonly used in SQL but not supported by typeorm (#2992).

I can use Object.assign or similar ways to manually map rows (like #1175), but this won’t apply my transformers (and possibly other typeorm specific stuff declared by annotations).

I suggest exposing some API which would at least allow for mapping a single row to an entity so that there is some way to keep using typeorm annotations while still being able to use unsupported SQL.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:15
  • Comments:16 (2 by maintainers)

github_iconTop GitHub Comments

19reactions
pasalinocommented, Apr 6, 2022

I think this is a necessary feature. There isn’t any manner to query a huge quantity of rows. The single way to perform that is to use stream but if I haven’t mapped Entity what is the advantage to use ORM? It’s a standard feature in many ORMs for instance Prisma. Please think to implement it.

15reactions
sgarnercommented, Jun 21, 2021

TypeORM has RawSqlResultsToEntityTransformer which can help with this mapping. The catch is that you need to pass a QueryExpressionMap instance to it which might be difficult to build manually.

However if you are able to define all your selected columns and joins etc using QueryBuilder and then modify the resulting query with your custom SQL requirements, then this will provide the QueryExpressionMap for you. I would imagine a UNION would be an applicable use case here if you can build at least one of the component queries using QueryBuilder and use string manipulation to combine them into a UNION.

For example in my use case I needed to use a locking mode in SQL Server that is not currently supported by TypeORM. I was able to create my query using QueryBuilder and then modify the lock expression in the SQL before executing it as a raw query. Then transform that into entities using RawSqlResultsToEntityTransformer.

Here is the code:

import { FindOptionsUtils } from 'typeorm';
import { RelationCountLoader } from 'typeorm/query-builder/relation-count/RelationCountLoader';
import { RelationIdLoader } from 'typeorm/query-builder/relation-id/RelationIdLoader';
import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer';

const qb = entityManager
  .getRepository(ExampleEntity)
  .createQueryBuilder('e')
  .setLock('pessimistic_write');

FindOptionsUtils.applyOptionsToQueryBuilder(qb, {
  relations: ['foobar'],
  where: {
    foo: 'bar',
  },
  order: {
    id: 'ASC',
  },
});

let [query, parameters] = qb.getQueryAndParameters();

// 👇 Here is where you can modify the SQL for the query to suit your requirements
query = query.replace(/ WITH \(UPDLOCK, ROWLOCK\) /, ' WITH (UPDLOCK, READPAST) ');

// Execute the SQL and get raw results
const rawResults = await entityManager.query(query, parameters);

const queryRunner = entityManager.connection.createQueryRunner();
const relationIdLoader = new RelationIdLoader(
  entityManager.connection,
  queryRunner,
  qb.expressionMap.relationIdAttributes,
);
const relationCountLoader = new RelationCountLoader(
  entityManager.connection,
  queryRunner,
  qb.expressionMap.relationCountAttributes,
);
const rawRelationIdResults = await relationIdLoader.load(rawResults);
const rawRelationCountResults = await relationCountLoader.load(rawResults);
const transformer = new RawSqlResultsToEntityTransformer(
  qb.expressionMap,
  entityManager.connection.driver,
  rawRelationIdResults,
  rawRelationCountResults,
  queryRunner,
);

// Transform the raw results into entities
const examples = transformer.transform(rawResults, qb.expressionMap.mainAlias);
Read more comments on GitHub >

github_iconTop Results From Across the Web

Execute Raw SQL Query in Entity Framework 6
Entity Framework 6.x allows you to execute the raw SQL query for the underlying relational database using SqlQuery() and ExecuteSqlCommand methods.
Read more >
Executing Raw SQL Queries using Entity Framework Core
Entity Framework Core provides mechanisms for executing raw SQL queries including stored procedures directly against the database.
Read more >
Raw SQL Queries - EF6 - Microsoft Learn
In this article. Writing SQL queries for entities; Writing SQL queries for non-entity types; Sending raw commands to the database.
Read more >
Native SQL - Doctrine Object Relational Mapper (ORM)
With NativeQuery you can execute native SELECT SQL statements and map the results to Doctrine entities or any other result format supported by...
Read more >
Doctrine Symfony - Use entity mapping with Raw SQL
Yes, doctrine offers a way to hydrate results of a native query into entities.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found