简体   繁体   English

未使用 TypeORM 找到连接“默认”

[英]Connection "default" was not found with TypeORM

I use TypeORM with NestJS and I am not able to save properly an entity.我将 TypeORM 与 NestJS 一起使用,但无法正确保存实体。

The connection creation works, postgres is running on 5432 port.连接创建工作,postgres 在 5432 端口上运行。 Credentials are OK too.凭证也可以。

However when I need to save a resource with entity.save() I got:但是,当我需要使用 entity.save() 保存资源时,我得到了:

Connection "default" was not found.


Error
    at new ConnectionNotFoundError (/.../ConnectionNotFoundError.ts:11:22)

I checked the source file of TypeORM ConnectionManager ( https://github.com/typeorm/typeorm/blob/master/src/connection/ConnectionManager.ts ) but it seems that the first time TypeORM creates connection it attributes "default" name if we don't provide one, which is the case for me.我检查了 TypeORM ConnectionManager 的源文件( https://github.com/typeorm/typeorm/blob/master/src/connection/ConnectionManager.ts )但似乎 TypeORM 第一次创建连接时它属性“默认”名称如果我们不提供,对我来说就是这种情况。

I setup TypeORM with TypeOrmModule as我将 TypeORM 与 TypeOrmModule 设置为

TypeOrmModule.forRoot({
      type: config.db.type,
      host: config.db.host,
      port: config.db.port,
      username: config.db.user,
      password: config.db.password,
      database: config.db.database,
      entities: [
        __dirname + '/../../dtos/entities/*.entity.js',
      ]
    })

Of course my constants are correct.当然,我的常数是正确的。 Any ideas?有任何想法吗?

You are trying to create a repository or manager without the connection being established.您正在尝试在未建立连接的情况下创建存储库或管理器。

Try doing this const shopkeeperRepository = getRepository(Shopkeeper);尝试这样做const shopkeeperRepository = getRepository(Shopkeeper); inside a function.在一个函数里面。 it will work它会起作用的

the upvoted answer is not necessarily correct, if you not specify the connection name it will default to "default".赞成的答案不一定正确,如果您不指定连接名称,它将默认为“默认”。

const manager = getConnectionManager().get('your_orm_name');
const repository = manager.getRepository<AModel>(Model);

If anyone else has this problem in the future, check this out just in case:如果以后有其他人遇到这个问题,请检查一下以防万一:

I accidentally did " user.save() " instead of " userRepo.save(user) ".我不小心做了“ user.save() ”而不是“ userRepo.save(user) ”。

(And of course above initializing the connection like this: (当然上面初始化连接是这样的:

const userRepo = getConnection(process.env.NODE_ENV).getRepository(User)

We are using lerna and using code from library A in package B .我们正在使用lerna并使用包B中库A中的代码。

The problem was that both TypeOrm versions in each package differ.问题是每个包中的两个 TypeOrm 版本都不同。

Solution is to make sure that you have exactly the same version installed in each package.解决方案是确保您在每个软件包中安装了完全相同的版本。

To be on the safe side, delete your node_modules directory and reinstall everything again with yarn install or npm install为了安全起见,请删除您的node_modules目录并使用yarn installnpm install重新安装所有内容

Check your yarn.lock for multiple entries of typeorm and make sure there is only one.检查您的yarn.lock是否有多个typeorm条目,并确保只有一个。

If anyone using Express Router with getRepository() , check the code below如果有人使用带有getRepository()的 Express Router,请检查下面的代码

const router = Router();

router.get("/", async function (req: Request, res: Response) {
  // here we will have logic to return all users
  const userRepository = getRepository(User);
  const users = await userRepository.find();
  res.json(users);
});

router.get("/:id", async function (req: Request, res: Response) {
  // here we will have logic to return user by id
  const userRepository = getRepository(User);
  const results = await userRepository.findOne(req.params.id);
  return res.send(results);
});

Just make sure to call getRepository() in every route just like Saras Arya said in the accepted answer.只需确保像 Saras Arya 在接受的答案中所说的那样在每条路线中调用getRepository()即可。

I follow the below approach creating the Database class.我按照以下方法创建Database类。 If the connection doesn't exist then it creates the connection else return the existing connection.如果连接不存在,则创建连接,否则返回现有连接。

import { Connection, ConnectionManager, ConnectionOptions, createConnection, getConnectionManager } from 'typeorm';

export class Database {
  private connectionManager: ConnectionManager;

  constructor() {
    this.connectionManager = getConnectionManager();
  }

  public async getConnection(name: string): Promise<Connection> {
    const CONNECTION_NAME: string = name;
    let connection: Connection;
    const hasConnection = this.connectionManager.has(CONNECTION_NAME);
    if (hasConnection) {
      connection = this.connectionManager.get(CONNECTION_NAME);
      if (!connection.isConnected) {
        connection = await connection.connect();
      }
    } else {

      const connectionOptions: ConnectionOptions = {
        name: 'default',
        type: 'mysql',
        host: 'localhost',
        port: 3306,
        username: 'root',
        password: 'password',
        database: 'DemoDb',
        synchronize: false,
        logging: true,
        entities: ['src/entities/**/*.js'],
        migrations: ['src/migration/**/*.js'],
        subscribers: ['src/subscriber/**/*.js'],
      };
      connection = await createConnection(connectionOptions);
    }
    return connection;
  }
}


If you are using webpack the make sure entities are imported specifically & returned in array.如果您使用的是 webpack,请确保实体是专门导入并以数组形式返回的。

    import {User} from 'src/entities/User.ts';
    import {Album} from 'src/entities/Album.ts';
    import {Photos} from 'src/entities/Photos.ts';
    const connectionOptions: ConnectionOptions = {
        name: 'default',
        type: 'mysql',
        host: 'localhost',
        port: 3306,
        username: 'root',
        password: 'password',
        database: 'DemoDb',
        synchronize: false,
        logging: true,
        entities: [User, Album, Photos],
        migrations: ['src/migration/**/*.js'],
        subscribers: ['src/subscriber/**/*.js'],
      };

Finally最后

  const connectionName = 'default';
  const database = new Database();
  const dbConn: Connection = await database.getConnection(connectionName);
  const MspRepository = dbConn.getRepository(Msp);
  await MspRepository.delete(mspId);

For those of you looking for another answer, check this out.对于那些正在寻找其他答案的人,请查看此内容。

In my case, the issue was because I was passing name in my db config.就我而言,问题是因为我在我的数据库配置中传递了name

export const dbConfig = {
    name: 'myDB',
    ...
}

await createConnection(dbConfig) // like this

As a result, the only connection server knows is myDB not default .结果,唯一的连接服务器知道myDB不是default

At the same time, in my service, repository was injected without name which will fallback to default .同时,在我的服务中,没有name的存储库被注入,这将回退到default (Service will looking for default connection as a result) (服务将因此寻找default连接)

@Service() // typedi
export class Service {
    constructor(
        // inject without name -> fallback to default
        @InjectRepository() private readonly repository
    ) {}
}

As a fix, I removed name property in my db config.作为修复,我删除了我的数据库配置中的name属性。

Or you can pass myDB as a parameter for InjectRepository like @InjectRepository('myDB') , either way works.或者您可以将myDB作为InjectRepository的参数传递,例如@InjectRepository('myDB') ,无论哪种方式都有效。

I got this error while using getConnectionOptions for different environments.在不同环境中使用getConnectionOptions时出现此错误。 Using one database for development and another for testing.使用一个数据库进行开发,另一个用于测试。 This is how I fixed it:这就是我修复它的方法:

const connectionOptions = await getConnectionOptions(process.env.NODE_ENV);
await createConnection({...connectionOptions, name:"default"});

I use getConnectionOptions to get the connection for the current environment, in order to do that successfully you have to change ormconfig.json to an array, with keys "name" containing the different environments you want, like so:我使用getConnectionOptions来获取当前环境的连接,为了成功地做到这一点,您必须将ormconfig.json更改为一个数组,其中包含您想要的不同环境的键“name”,如下所示:

[
{
    "name" : "development",
    "type": "USER",
    "host": "localhost",
    "port": 5432,
    "username": "postgres",
    "password": "PASS",
    "database": "YOURDB"
},
{
    "name" : "test",
    "type": "USERTEST",
    "host": "localhost",
    "port": 5432,
    "username": "postgres",
    "password": "PASSTEST",
    "database": "YOURDBTEST"
}
]

Now connectionOptions will contain the connection parameters of the current environment, but loading it to createConnection threw the error you pointed.现在connectionOptions将包含当前环境的连接参数,但是将其加载到createConnection会引发您指出的错误。 Changing connectionOptions name to "default" fixed the issue.connectionOptions名称更改为“默认”解决了该问题。

I know it is super weird but someone might need this:我知道这很奇怪,但有人可能需要这个:

Windows related reason. Windows相关的原因。

I had the same error caused by the current location set with the drive letter in the lower case ( d:/apps/app-name/etc ).我遇到了由小写驱动器号( d:/apps/app-name/etc )设置的当前位置引起的相同错误。
The problem got fixed once I updated the directory change instruction to use capital D ( D:/apps/app-name/etc ).一旦我更新目录更改指令以使用大写D ( D:/apps/app-name/etc ),问题就得到了解决。

After verifying TypeOrm versions is same in both the packages ie- external package and consumer repository as mentioned by @InsOp still issue persist then issue could be-在验证两个包中的 TypeOrm 版本相同后,即@InsOp 提到的外部包和消费者存储库仍然存在问题,那么问题可能是 -

Basically when we create an external package - TypeORM tries to get the "default" connection option, but If not found then throws an error:基本上,当我们创建一个外部包时——TypeORM 会尝试获取“默认”连接选项,但如果未找到,则会引发错误:

ConnectionNotFoundError: Connection "default" was not found. ConnectionNotFoundError:未找到连接“默认”。

We can solve this issue by doing some kind of sanity check before establishing a connection - luckily we have .has() method on getConnectionManager() .我们可以通过在建立连接之前进行某种健全性检查来解决这个问题——幸运的是,我们在getConnectionManager()上有.has()方法。

import { Connection, getConnectionManager, getConnectionOptions, 
  createConnection, getConnection, QueryRunner } from 'typeorm';
    
    async init() {
    let connection: Connection;
    let queryRunner: QueryRunner;

     if (!getConnectionManager().has('default')) {
        const connectionOptions = await getConnectionOptions();
        connection = await createConnection(connectionOptions);
      } else {
        connection = getConnection();
      }

    queryRunner = connection.createQueryRunner(); 
 }

Above is a quick code-snippet which was the actual root cause for this issue but If you are interested to see complete working repositories (different examples) -上面是一个快速代码片段,它是此问题的实际根本原因,但如果您有兴趣查看完整的工作存储库(不同示例) -

  • External NPM Package :外部 NPM 包:
  • Consumer of above package : nest-typeorm-postgre (specific files- package.json, src/countries/countries.service.ts & countries.module.ts )上述包的消费者: nest-typeorm-postgre (具体文件-package.json , src/countries/countries.service.ts & countries.module.ts

In my case was that I have an array of multiple connections, instead of just one.就我而言,我有一组多个连接,而不仅仅是一个。 You have 2 alternatives.你有 2 个选择。

  • To have at least one default named connection, example:要拥有至少一个default命名连接,例如:
createConnections([
  {
    name: 'default',
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'root',
    password: 'root',
    database: 'users',
    entities: [`${__dirname}/entity/*{.js,.ts}`],
    synchronize: true,
    logging: true
  }
]);
  • To be specific when using the connection:具体使用连接时:
import {getConnection} from "typeorm";

const db1Connection = getConnection("db1Connection");
// you can work with "db1" database now...

For those who still looking for an answer, I found one that helped me.对于那些仍在寻找答案的人,我找到了一个对我有帮助的人。 I'm using TypeORM with Express and seems like that Express execute the connection first than typeorm.我正在将 TypeORM 与 Express 一起使用,似乎 Express 先执行连接而不是 typeorm。 marc_s gave this answer on this link marc_s 在这个链接上给出了这个答案

https://stackoverflow.com/a/63270362/11429504 https://stackoverflow.com/a/63270362/11429504

In my own case, the actual problem was that my index file imports my router file which imports my controllers which then import my services (where the call to getRepository was made).在我自己的情况下,实际问题是我的index文件导入了我的router文件,该文件导入了我的控制器,然后导入了我的服务(调用getRepository的地方)。 So the imports were resolving (and thus the call to getRepository ) before the connection was established.因此,在建立连接之前,导入正在解析(以及对getRepository的调用)。

I considered implementing Sarya's answer but it's going to leave my code more verbose.我考虑实施Sarya 的答案,但它会让我的代码更加冗长。

What I did was create a function to connect to the DB in a db/index.ts file我所做的是创建一个函数来连接到db/index.ts文件中的数据库

import { createConnection } from "typeorm";

export const getDBConnection = async () => {
  const dbConnection = await createConnection();
  if (!dbConnection.isConnected) await dbConnection.connect();
  return dbConnection;
}

Then create an async function to bootstrap my app.然后创建一个异步函数来引导我的应用程序。 I wait on getDBConnection to resolve before instantiating my app then I import my router file after.在实例化我的应用程序之前,我等待getDBConnection解决,然后我导入我的路由器文件。 That way the import resolution only happens after the connection has been established.这样,导入解析仅在建立连接后发生。

routers/index.ts

import { Router } from 'express';

const router = Router();

/* ... route configurations ... */

export default router;

app.ts

const bootstrap = async () => {
  try {
    // wait on connection to be established
    await getDBConnection();
  } catch (error) {
    // log error then throw
    throw error;
  }

  // create app
  const app = express();

  // some middleware configuration...

  // now import and setup the router
  const { default: router } = await import("./routers");
  app.use("/api", router);

  // some more middleware configuration...

  const server = http.createServer(app);
  server.listen(3000, () => console.log('app running at port: 3000'));
};

bootstrap();

I had this same problem with the following code:我对以下代码有同样的问题:

import { HttpException, Inject, NotFoundException } from "@nestjs/common";
import { Not } from "typeorm";
import { Transactional } from "typeorm-transactional-cls-hooked";
import { TENANT_CONNECTION } from "../tenant/tenant.module";
import {Feriados} from './feriados.entity';  

export class FeriadosService {
   repository: any;

constructor(
@Inject(TENANT_CONNECTION) private connection)
{
  this.repository = connection.getRepository(Feriados)
}

@Transactional()
async agregar(tablaNueva: Feriados): Promise<Number> {
  const tablaAGuardar = await this.repository.create(tablaNueva)
  return await this.guardar(tablaAGuardar)
}

@Transactional()
async actualizar(tablaActualizada: Feriados): Promise<Number>{
  const tablaAGuardar = await this.repository.merge(tablaActualizada);
  return await this.guardar(tablaAGuardar)
}

async guardar(tabla:Feriados){ 
  await this.repository.save(tabla)
  return tabla.id 
}

I fixed it by removing the 2 @Transactional() I hope someone helps.我通过删除 2 @Transactional() 来修复它,希望有人帮助。

In typeorm v0.3 the Connection API was replaced by the DataSource API.typeorm v0.3中, Connection API 被DataSource API 替换。 NestJS adapted this change as well, so if you relied on the old API (eg getConnection method) you might see the Connection "default" was not found error. NestJS 也适应了这一变化,因此如果您依赖旧的 API(例如getConnection方法),您可能会看到Connection "default" was not found错误。

You can read about the changes and the new API in the release notes: https://github.com/typeorm/typeorm/releases/tag/0.3.0您可以在发行说明中阅读有关更改和新 API 的信息: https://github.com/typeorm/typeorm/releases/tag/0.3.0

If you used getConnection you can use app.get(DataSource) instead.如果您使用getConnection ,则可以改用app.get(DataSource)

In the new version of Typeorm, 0.3.7, a solution to this problem is next:在新版本的 Typeorm 0.3.7 中,下一个解决这个问题的方法是:

  1. In the app.module.ts, change the constructor of the AppModule class and create a method to return Datasource:在 app.module.ts 中,更改 AppModule class 的构造函数并创建一个返回 Datasource 的方法:

     export class AppModule { constructor(private dataSource: DataSource) {} getDataSource() { return this.dataSource; } }
  2. Then, in the file you need to use add:然后,在您需要使用的文件中添加:

     const repository = app.get(AppModule).getDataSource().getRepository('Entity_name');

Although Saras Arya has provided the correct answer, I have encountered the same error虽然 Saras Arya 提供了正确的答案,但我遇到了同样的错误

ConnectionNotFoundError: Connection "default" was not found. ConnectionNotFoundError:未找到连接“默认”。

due to the fact that my typeORM entity did have an @Entity() decorator as well as that it had extended BaseEntity .由于我的typeORM实体确实有一个@Entity()装饰器以及它扩展了BaseEntity

The two can't live together.两个人不能住在一起。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM