簡體   English   中英

未使用 TypeORM 找到連接“默認”

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

我將 TypeORM 與 NestJS 一起使用,但無法正確保存實體。

連接創建工作,postgres 在 5432 端口上運行。 憑證也可以。

但是,當我需要使用 entity.save() 保存資源時,我得到了:

Connection "default" was not found.


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

我檢查了 TypeORM ConnectionManager 的源文件( https://github.com/typeorm/typeorm/blob/master/src/connection/ConnectionManager.ts )但似乎 TypeORM 第一次創建連接時它屬性“默認”名稱如果我們不提供,對我來說就是這種情況。

我將 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',
      ]
    })

當然,我的常數是正確的。 有任何想法嗎?

您正在嘗試在未建立連接的情況下創建存儲庫或管理器。

嘗試這樣做const shopkeeperRepository = getRepository(Shopkeeper); 在一個函數里面。 它會起作用的

贊成的答案不一定正確,如果您不指定連接名稱,它將默認為“默認”。

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

如果以后有其他人遇到這個問題,請檢查一下以防萬一:

我不小心做了“ user.save() ”而不是“ userRepo.save(user) ”。

(當然上面初始化連接是這樣的:

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

我們正在使用lerna並使用包B中庫A中的代碼。

問題是每個包中的兩個 TypeOrm 版本都不同。

解決方案是確保您在每個軟件包中安裝了完全相同的版本。

為了安全起見,請刪除您的node_modules目錄並使用yarn installnpm install重新安裝所有內容

檢查您的yarn.lock是否有多個typeorm條目,並確保只有一個。

如果有人使用帶有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);
});

只需確保像 Saras Arya 在接受的答案中所說的那樣在每條路線中調用getRepository()即可。

我按照以下方法創建Database類。 如果連接不存在,則創建連接,否則返回現有連接。

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;
  }
}


如果您使用的是 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'],
      };

最后

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

對於那些正在尋找其他答案的人,請查看此內容。

就我而言,問題是因為我在我的數據庫配置中傳遞了name

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

await createConnection(dbConfig) // like this

結果,唯一的連接服務器知道myDB不是default

同時,在我的服務中,沒有name的存儲庫被注入,這將回退到default (服務將因此尋找default連接)

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

作為修復,我刪除了我的數據庫配置中的name屬性。

或者您可以將myDB作為InjectRepository的參數傳遞,例如@InjectRepository('myDB') ,無論哪種方式都有效。

在不同環境中使用getConnectionOptions時出現此錯誤。 使用一個數據庫進行開發,另一個用於測試。 這就是我修復它的方法:

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

我使用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"
}
]

現在connectionOptions將包含當前環境的連接參數,但是將其加載到createConnection會引發您指出的錯誤。 connectionOptions名稱更改為“默認”解決了該問題。

我知道這很奇怪,但有人可能需要這個:

Windows相關的原因。

我遇到了由小寫驅動器號( d:/apps/app-name/etc )設置的當前位置引起的相同錯誤。
一旦我更新目錄更改指令以使用大寫D ( D:/apps/app-name/etc ),問題就得到了解決。

在驗證兩個包中的 TypeOrm 版本相同后,即@InsOp 提到的外部包和消費者存儲庫仍然存在問題,那么問題可能是 -

基本上,當我們創建一個外部包時——TypeORM 會嘗試獲取“默認”連接選項,但如果未找到,則會引發錯誤:

ConnectionNotFoundError:未找到連接“默認”。

我們可以通過在建立連接之前進行某種健全性檢查來解決這個問題——幸運的是,我們在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(); 
 }

上面是一個快速代碼片段,它是此問題的實際根本原因,但如果您有興趣查看完整的工作存儲庫(不同示例) -

  • 外部 NPM 包:
  • 上述包的消費者: nest-typeorm-postgre (具體文件-package.json , src/countries/countries.service.ts & countries.module.ts

就我而言,我有一組多個連接,而不僅僅是一個。 你有 2 個選擇。

  • 要擁有至少一個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
  }
]);
  • 具體使用連接時:
import {getConnection} from "typeorm";

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

對於那些仍在尋找答案的人,我找到了一個對我有幫助的人。 我正在將 TypeORM 與 Express 一起使用,似乎 Express 先執行連接而不是 typeorm。 marc_s 在這個鏈接上給出了這個答案

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

在我自己的情況下,實際問題是我的index文件導入了我的router文件,該文件導入了我的控制器,然后導入了我的服務(調用getRepository的地方)。 因此,在建立連接之前,導入正在解析(以及對getRepository的調用)。

我考慮實施Sarya 的答案,但它會讓我的代碼更加冗長。

我所做的是創建一個函數來連接到db/index.ts文件中的數據庫

import { createConnection } from "typeorm";

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

然后創建一個異步函數來引導我的應用程序。 在實例化我的應用程序之前,我等待getDBConnection解決,然后我導入我的路由器文件。 這樣,導入解析僅在建立連接后發生。

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();

我對以下代碼有同樣的問題:

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 
}

我通過刪除 2 @Transactional() 來修復它,希望有人幫助。

typeorm v0.3中, Connection API 被DataSource API 替換。 NestJS 也適應了這一變化,因此如果您依賴舊的 API(例如getConnection方法),您可能會看到Connection "default" was not found錯誤。

您可以在發行說明中閱讀有關更改和新 API 的信息: https://github.com/typeorm/typeorm/releases/tag/0.3.0

如果您使用getConnection ,則可以改用app.get(DataSource)

在新版本的 Typeorm 0.3.7 中,下一個解決這個問題的方法是:

  1. 在 app.module.ts 中,更改 AppModule class 的構造函數並創建一個返回 Datasource 的方法:

     export class AppModule { constructor(private dataSource: DataSource) {} getDataSource() { return this.dataSource; } }
  2. 然后,在您需要使用的文件中添加:

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

雖然 Saras Arya 提供了正確的答案,但我遇到了同樣的錯誤

ConnectionNotFoundError:未找到連接“默認”。

由於我的typeORM實體確實有一個@Entity()裝飾器以及它擴展了BaseEntity

兩個人不能住在一起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM