# DataService
{{< generation-info sourceFile="packages/admin-ui/src/lib/core/src/data/providers/data.service.ts" sourceLine="33" packageName="
@vendure/admin-ui">}}
Used to interact with the Admin API via GraphQL queries. Internally this service uses the
Apollo Client, which means it maintains a normalized entity cache. For this reason, it is
advisable to always select the `id` field of any entity, which will allow the returned data
to be effectively cached.
## Signature
```TypeScript
class DataService {
query(query: DocumentNode | TypedDocumentNode, variables?: V, fetchPolicy: WatchQueryFetchPolicy = 'cache-and-network') => QueryResult;
mutate(mutation: DocumentNode | TypedDocumentNode, variables?: V, update?: MutationUpdaterFn) => Observable;
}
```
## Members
### query
{{< member-info kind="method" type="(query: DocumentNode | TypedDocumentNode<T, V>, variables?: V, fetchPolicy: WatchQueryFetchPolicy = 'cache-and-network') =>
QueryResult<T, V>" >}}
{{< member-description >}}Perform a GraphQL query. Returns a
QueryResult which allows further control over
they type of result returned, e.g. stream of values, single value etc.
*Example*
```TypeScript
const result$ = this.dataService.query(gql`
query MyQuery($id: ID!) {
product(id: $id) {
id
name
slug
}
},
{ id: 123 },
).mapSingle(data => data.product);
```{{< /member-description >}}
### mutate
{{< member-info kind="method" type="(mutation: DocumentNode | TypedDocumentNode<T, V>, variables?: V, update?: MutationUpdaterFn<T>) => Observable<T>" >}}
{{< member-description >}}Perform a GraphQL mutation.
*Example*
```TypeScript
const result$ = this.dataService.mutate(gql`
mutation MyMutation($Codegen.UpdateEntityInput!) {
updateEntity(input: $input) {
id
name
}
},
{ Codegen.updateEntityInput },
);
```{{< /member-description >}}
# QueryResult
{{< generation-info sourceFile="packages/admin-ui/src/lib/core/src/data/query-result.ts" sourceLine="19" packageName="
@vendure/admin-ui">}}
This class wraps the Apollo Angular QueryRef object and exposes some getters
for convenience.
## Signature
```TypeScript
class QueryResult = Record> {
constructor(queryRef: QueryRef, apollo: Apollo)
completed$ = new Subject();
refetchOnChannelChange() => QueryResult;
single$: Observable
stream$: Observable
ref: QueryRef
mapSingle(mapFn: (item: T) => R) => Observable;
mapStream(mapFn: (item: T) => R) => Observable;
}
```
## Members
### constructor
{{< member-info kind="method" type="(queryRef: QueryRef<T, V>, apollo: Apollo) => QueryResult" >}}
{{< member-description >}}{{< /member-description >}}
### completed$
{{< member-info kind="property" type="" >}}
{{< member-description >}}{{< /member-description >}}
### refetchOnChannelChange
{{< member-info kind="method" type="() =>
QueryResult<T, V>" >}}
{{< member-description >}}Re-fetch this query whenever the active Channel changes.{{< /member-description >}}
### single$
{{< member-info kind="property" type="Observable<T>" >}}
{{< member-description >}}Returns an Observable which emits a single result and then completes.{{< /member-description >}}
### stream$
{{< member-info kind="property" type="Observable<T>" >}}
{{< member-description >}}Returns an Observable which emits until unsubscribed.{{< /member-description >}}
### ref
{{< member-info kind="property" type="QueryRef<T, V>" >}}
{{< member-description >}}{{< /member-description >}}
### mapSingle
{{< member-info kind="method" type="(mapFn: (item: T) => R) => Observable<R>" >}}
{{< member-description >}}Returns a single-result Observable after applying the map function.{{< /member-description >}}
### mapStream
{{< member-info kind="method" type="(mapFn: (item: T) => R) => Observable<R>" >}}
{{< member-description >}}Returns a multiple-result Observable after applying the map function.{{< /member-description >}}