***

title: "Implementing ChannelAware"
metaTitle: "Making Custom Entities Channel-Aware in Vendure"
metaDescription: "Scope custom entities to specific Vendure channels by implementing the ChannelAware interface for multi-tenant and multi-store data isolation."
-----------------------------------------------------------------------------------------------------------------------------------------------------------------

## Defining channel-aware entities

Making an entity channel-aware means that it can be associated with a specific [Channel](/current/core/reference/typescript-api/entities/channel).
This is useful when you want to have different data or features for different channels. First you will have to create
an entity ([Define a database entity](/current/core/developer-guide/database-entity/)) that implements the `ChannelAware` interface.
This interface requires the entity to provide a `channels` property

```ts title="src/plugins/requests/entities/product-request.entity.ts"
import { DeepPartial } from '@vendure/common/lib/shared-types';
import { VendureEntity, Product, EntityId, ID, ChannelAware } from '@vendure/core';
import { Column, Entity, ManyToOne } from 'typeorm';

@Entity()
class ProductRequest extends VendureEntity implements ChannelAware {
    constructor(input?: DeepPartial<ProductRequest>) {
        super(input);
    }

    @ManyToOne(type => Product)
    product: Product;

    @EntityId()
    productId: ID;

    @Column()
    text: string;
    
    @ManyToMany(() => Channel) // [!code highlight]
    @JoinTable() // [!code highlight]
    channels: Channel[]; // [!code highlight]
}
```

## Creating channel-aware entities

Creating a channel-aware entity is similar to creating a regular entity. The only difference is that you need to assign the entity to the current channel.
This can be done by using the `ChannelService` which provides the `assignToCurrentChannel` helper function.

:::info
The `assignToCurrentChannel` function will only assign the `channels` property of the entity. You will still need to save the entity to the database.
:::

```ts title="src/plugins/requests/service/product-request.service.ts"
import { ChannelService } from '@vendure/core';

export class RequestService {

    constructor(private channelService: ChannelService) {}

    async create(ctx: RequestContext, input: CreateRequestInput): Promise<ProductRequest> {
        const request = new ProductRequest(input);
        // Now we need to assign the request to the current channel (+ default channel)
        await this.channelService.assignToCurrentChannel(input, ctx); // [!code highlight]
        
        return await this.connection.getRepository(ProductRequest).save(request);
    }
}
```

For [Translatable entities](/current/core/developer-guide/translations/), the best place to assign the channels is inside the `beforeSave` input of the [TranslatableSaver](/current/core/reference/typescript-api/service-helpers/translatable-saver/) helper class.

## Querying channel-aware entities

When querying channel-aware entities, you can use the [ListQueryBuilder](/current/core/reference/typescript-api/data-access/list-query-builder/#extendedlistqueryoptions) or
the [TransactionalConnection](/current/core/reference/typescript-api/data-access/transactional-connection/#findoneinchannel) to automatically filter entities based on the provided channel id.

```ts title="src/plugins/requests/service/product-request.service.ts"
import { ChannelService, ListQueryBuilder, TransactionalConnection } from '@vendure/core';

export class RequestService {

    constructor(
        private connection: TransactionalConnection,
        private listQueryBuilder: ListQueryBuilder,
        private channelService: ChannelService) {}

    findOne(ctx: RequestContext,
            requestId: ID,
            relations?: RelationPaths<ProductRequest>) {
        return this.connection.findOneInChannel(ctx, ProductRequest, requestId, ctx.channelId, { // [!code highlight]
            relations: unique(effectiveRelations) // [!code highlight]
        }); // [!code highlight]
    }

    findAll(
        ctx: RequestContext,
        options?: ProductRequestListOptions,
        relations?: RelationPaths<ProductRequest>,
    ): Promise<PaginatedList<ProductRequest>> {
        return this.listQueryBuilder
            .build(ProductRequest, options, {
                ctx,
                relations,
                channelId: ctx.channelId, // [!code highlight]
            })
            .getManyAndCount()
            .then(([items, totalItems]) => {
                return {
                    items,
                    totalItems,
                };
            });
    }
}
```
