示例#1
0
        public override async Task <ExtendedQueryTagStoreJoinEntry> GetExtendedQueryTagAsync(string path, CancellationToken cancellationToken = default)
        {
            using (SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken))
                using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand())
                {
                    VLatest.GetExtendedQueryTag.PopulateCommand(sqlCommandWrapper, path);

                    var executionTimeWatch = Stopwatch.StartNew();
                    using (var reader = await sqlCommandWrapper.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken))
                    {
                        if (!await reader.ReadAsync(cancellationToken))
                        {
                            throw new ExtendedQueryTagNotFoundException(string.Format(DicomCoreResource.ExtendedQueryTagNotFound, path));
                        }

                        (int tagKey, string tagPath, string tagVR, string tagPrivateCreator, int tagLevel, int tagStatus, byte queryStatus, int errorCount, Guid? operationId) = reader.ReadRow(
                            VLatest.ExtendedQueryTag.TagKey,
                            VLatest.ExtendedQueryTag.TagPath,
                            VLatest.ExtendedQueryTag.TagVR,
                            VLatest.ExtendedQueryTag.TagPrivateCreator,
                            VLatest.ExtendedQueryTag.TagLevel,
                            VLatest.ExtendedQueryTag.TagStatus,
                            VLatest.ExtendedQueryTag.QueryStatus,
                            VLatest.ExtendedQueryTag.ErrorCount,
                            VLatest.ExtendedQueryTagOperation.OperationId.AsNullable());

                        executionTimeWatch.Stop();
                        Logger.StoredProcedureSucceeded(nameof(VLatest.GetExtendedQueryTag), executionTimeWatch);

                        return(new ExtendedQueryTagStoreJoinEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, (QueryStatus)queryStatus, errorCount, operationId));
                    }
                }
        }
示例#2
0
        public override async Task <IReadOnlyList <ExtendedQueryTagStoreEntry> > GetExtendedQueryTagsAsync(Guid operationId, CancellationToken cancellationToken = default)
        {
            var results = new List <ExtendedQueryTagStoreEntry>();

            using (SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken))
                using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand())
                {
                    VLatest.GetExtendedQueryTagsByOperation.PopulateCommand(sqlCommandWrapper, operationId);

                    using (SqlDataReader reader = await sqlCommandWrapper.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken))
                    {
                        while (await reader.ReadAsync(cancellationToken))
                        {
                            (int tagKey, string tagPath, string tagVR, string tagPrivateCreator, int tagLevel, int tagStatus, byte queryStatus, int errorCount) = reader.ReadRow(
                                VLatest.ExtendedQueryTag.TagKey,
                                VLatest.ExtendedQueryTag.TagPath,
                                VLatest.ExtendedQueryTag.TagVR,
                                VLatest.ExtendedQueryTag.TagPrivateCreator,
                                VLatest.ExtendedQueryTag.TagLevel,
                                VLatest.ExtendedQueryTag.TagStatus,
                                VLatest.ExtendedQueryTag.QueryStatus,
                                VLatest.ExtendedQueryTag.ErrorCount);

                            results.Add(new ExtendedQueryTagStoreEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, (QueryStatus)queryStatus, errorCount));
                        }
                    }
                }

            return(results);
        }
示例#3
0
        public override async Task <IReadOnlyList <int> > CompleteReindexingAsync(IReadOnlyCollection <int> queryTagKeys, CancellationToken cancellationToken = default)
        {
            EnsureArg.HasItems(queryTagKeys, nameof(queryTagKeys));

            using SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken);

            using SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand();

            IEnumerable <ExtendedQueryTagKeyTableTypeV1Row> rows = queryTagKeys.Select(x => new ExtendedQueryTagKeyTableTypeV1Row(x));

            VLatest.CompleteReindexing.PopulateCommand(sqlCommandWrapper, rows);

            try
            {
                var keys = new List <int>();
                using SqlDataReader reader = await sqlCommandWrapper.ExecuteReaderAsync(cancellationToken);

                while (await reader.ReadAsync(cancellationToken))
                {
                    keys.Add(reader.ReadRow(VLatest.ExtendedQueryTagString.TagKey));
                }

                return(keys);
            }
            catch (SqlException ex)
            {
                throw new DataStoreException(ex);
            }
        }
示例#4
0
        public override async Task AddExtendedQueryTagErrorAsync(
            int tagKey,
            ValidationErrorCode errorCode,
            long watermark,
            CancellationToken cancellationToken = default)
        {
            EnsureArg.EnumIsDefined(errorCode, nameof(errorCode));

            using SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken);

            using SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand();
            VLatest.AddExtendedQueryTagError.PopulateCommand(
                sqlCommandWrapper,
                tagKey,
                (short)errorCode,
                watermark);

            try
            {
                await sqlCommandWrapper.ExecuteNonQueryAsync(cancellationToken);
            }
            catch (SqlException e)
            {
                if (e.Number == SqlErrorCodes.NotFound)
                {
                    throw new ExtendedQueryTagNotFoundException(
                              string.Format(
                                  CultureInfo.InvariantCulture,
                                  DicomSqlServerResource.ExtendedQueryTagNotFoundWhenAddingError,
                                  tagKey));
                }

                throw new DataStoreException(e);
            }
        }
示例#5
0
        private async Task <List <ExtendedQueryTagStoreJoinEntry> > GetAllExtendedQueryTagsAsync(CancellationToken cancellationToken = default)
        {
            var results = new List <ExtendedQueryTagStoreJoinEntry>();

            using (SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken))
                using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand())
                {
                    // V2 version allows NULL to get all tags
                    V2.GetExtendedQueryTag.PopulateCommand(sqlCommandWrapper, null);

                    var executionTimeWatch = Stopwatch.StartNew();
                    using (var reader = await sqlCommandWrapper.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken))
                    {
                        while (await reader.ReadAsync(cancellationToken))
                        {
                            (int tagKey, string tagPath, string tagVR, string tagPrivateCreator, int tagLevel, int tagStatus) = reader.ReadRow(
                                V2.ExtendedQueryTag.TagKey,
                                V2.ExtendedQueryTag.TagPath,
                                V2.ExtendedQueryTag.TagVR,
                                V2.ExtendedQueryTag.TagPrivateCreator,
                                V2.ExtendedQueryTag.TagLevel,
                                V2.ExtendedQueryTag.TagStatus);

                            results.Add(new ExtendedQueryTagStoreJoinEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, QueryStatus.Enabled, 0));
                        }

                        executionTimeWatch.Stop();
                        Logger.StoredProcedureSucceeded(nameof(V2.GetExtendedQueryTag), executionTimeWatch);
                    }
                }

            return(results);
        }
示例#6
0
        public override async Task DeleteExtendedQueryTagAsync(string tagPath, string vr, CancellationToken cancellationToken = default)
        {
            using (SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken))
                using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand())
                {
                    V2.DeleteExtendedQueryTag.PopulateCommand(sqlCommandWrapper, tagPath, (byte)ExtendedQueryTagLimit.ExtendedQueryTagVRAndDataTypeMapping[vr]);

                    try
                    {
                        await sqlCommandWrapper.ExecuteNonQueryAsync(cancellationToken);
                    }
                    catch (SqlException ex)
                    {
                        switch (ex.Number)
                        {
                        case SqlErrorCodes.NotFound:
                            throw new ExtendedQueryTagNotFoundException(
                                      string.Format(CultureInfo.InvariantCulture, DicomSqlServerResource.ExtendedQueryTagNotFound, tagPath));

                        case SqlErrorCodes.PreconditionFailed:
                            throw new ExtendedQueryTagBusyException(
                                      string.Format(CultureInfo.InvariantCulture, DicomSqlServerResource.ExtendedQueryTagIsBusy, tagPath));

                        default:
                            throw new DataStoreException(ex);
                        }
                    }
                }
        }
示例#7
0
        public override async Task <IReadOnlyList <ExtendedQueryTagStoreEntry> > AssignReindexingOperationAsync(
            IReadOnlyCollection <int> queryTagKeys,
            Guid operationId,
            bool returnIfCompleted = false,
            CancellationToken cancellationToken = default)
        {
            EnsureArg.HasItems(queryTagKeys, nameof(queryTagKeys));

            using SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken);

            using SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand();

            IEnumerable <ExtendedQueryTagKeyTableTypeV1Row> rows = queryTagKeys.Select(x => new ExtendedQueryTagKeyTableTypeV1Row(x));

            VLatest.AssignReindexingOperation.PopulateCommand(sqlCommandWrapper, rows, operationId, returnIfCompleted);

            try
            {
                var queryTags = new List <ExtendedQueryTagStoreEntry>();
                using SqlDataReader reader = await sqlCommandWrapper.ExecuteReaderAsync(cancellationToken);

                while (await reader.ReadAsync(cancellationToken))
                {
                    (int tagKey, string tagPath, string tagVR, string tagPrivateCreator, byte tagLevel, byte tagStatus, byte queryStatus, int errorCount) = reader.ReadRow(
                        VLatest.ExtendedQueryTag.TagKey,
                        VLatest.ExtendedQueryTag.TagPath,
                        VLatest.ExtendedQueryTag.TagVR,
                        VLatest.ExtendedQueryTag.TagPrivateCreator,
                        VLatest.ExtendedQueryTag.TagLevel,
                        VLatest.ExtendedQueryTag.TagStatus,
                        VLatest.ExtendedQueryTag.QueryStatus,
                        VLatest.ExtendedQueryTag.ErrorCount);

                    queryTags.Add(new ExtendedQueryTagStoreEntry(
                                      tagKey,
                                      tagPath,
                                      tagVR,
                                      tagPrivateCreator,
                                      (QueryTagLevel)tagLevel,
                                      (ExtendedQueryTagStatus)tagStatus,
                                      (QueryStatus)queryStatus,
                                      errorCount));
                }

                return(queryTags);
            }
            catch (SqlException ex)
            {
                throw new DataStoreException(ex);
            }
        }
示例#8
0
        public override async Task <IReadOnlyList <ExtendedQueryTagStoreEntry> > AddExtendedQueryTagsAsync(
            IReadOnlyCollection <AddExtendedQueryTagEntry> extendedQueryTagEntries,
            int maxAllowedCount,
            bool ready = false,
            CancellationToken cancellationToken = default)
        {
            EnsureArg.IsNotNull(extendedQueryTagEntries, nameof(extendedQueryTagEntries));
            EnsureArg.IsGt(maxAllowedCount, 0, nameof(maxAllowedCount));

            using SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken);

            using SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand();

            IEnumerable <AddExtendedQueryTagsInputTableTypeV1Row> rows = extendedQueryTagEntries.Select(ToAddExtendedQueryTagsInputTableTypeV1Row);

            VLatest.AddExtendedQueryTags.PopulateCommand(sqlCommandWrapper, maxAllowedCount, ready, new VLatest.AddExtendedQueryTagsTableValuedParameters(rows));

            try
            {
                var results = new List <ExtendedQueryTagStoreEntry>();
                using SqlDataReader reader = await sqlCommandWrapper.ExecuteReaderAsync(cancellationToken);

                while (await reader.ReadAsync(cancellationToken))
                {
                    (int tagKey, string tagPath, string tagVR, string tagPrivateCreator, int tagLevel, int tagStatus, byte queryStatus, int errorCount) = reader.ReadRow(
                        VLatest.ExtendedQueryTag.TagKey,
                        VLatest.ExtendedQueryTag.TagPath,
                        VLatest.ExtendedQueryTag.TagVR,
                        VLatest.ExtendedQueryTag.TagPrivateCreator,
                        VLatest.ExtendedQueryTag.TagLevel,
                        VLatest.ExtendedQueryTag.TagStatus,
                        VLatest.ExtendedQueryTag.QueryStatus,
                        VLatest.ExtendedQueryTag.ErrorCount);

                    results.Add(new ExtendedQueryTagStoreEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, (QueryStatus)queryStatus, errorCount));
                }

                return(results);
            }
            catch (SqlException ex)
            {
                throw ex.Number switch
                      {
                          SqlErrorCodes.Conflict => ex.State == 1
                        ? new ExtendedQueryTagsExceedsMaxAllowedCountException(maxAllowedCount)
                        : new ExtendedQueryTagsAlreadyExistsException(),
                          _ => new DataStoreException(ex),
                      };
            }
        }
示例#9
0
        public override async Task <IReadOnlyList <ExtendedQueryTagError> > GetExtendedQueryTagErrorsAsync(string tagPath, int limit, int offset, CancellationToken cancellationToken = default)
        {
            List <ExtendedQueryTagError> results = new List <ExtendedQueryTagError>();

            using SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken);

            using SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand();

            VLatest.GetExtendedQueryTagErrorsV6.PopulateCommand(sqlCommandWrapper, tagPath, limit, offset);

            try
            {
                using SqlDataReader reader = await sqlCommandWrapper.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken);

                while (await reader.ReadAsync(cancellationToken))
                {
                    (int tagkey, short errorCode, DateTime createdTime, string partitionName, string studyInstanceUid, string seriesInstanceUid, string sopInstanceUid) = reader.ReadRow(
                        VLatest.ExtendedQueryTagError.TagKey,
                        VLatest.ExtendedQueryTagError.ErrorCode,
                        VLatest.ExtendedQueryTagError.CreatedTime,
                        VLatest.Partition.PartitionName,
                        VLatest.Instance.StudyInstanceUid,
                        VLatest.Instance.SeriesInstanceUid,
                        VLatest.Instance.SopInstanceUid);

                    results.Add(new ExtendedQueryTagError(createdTime, studyInstanceUid, seriesInstanceUid, sopInstanceUid, ((ValidationErrorCode)errorCode).GetMessage(), partitionName));
                }
            }
            catch (SqlException e)
            {
                if (e.Number == SqlErrorCodes.NotFound)
                {
                    throw new ExtendedQueryTagNotFoundException(
                              string.Format(CultureInfo.InvariantCulture, DicomSqlServerResource.ExtendedQueryTagNotFound, tagPath));
                }

                throw new DataStoreException(e);
            }

            return(results);
        }
示例#10
0
        public override async Task <IReadOnlyList <ExtendedQueryTagStoreJoinEntry> > GetExtendedQueryTagsAsync(int limit, int offset = 0, CancellationToken cancellationToken = default)
        {
            EnsureArg.IsGte(limit, 1, nameof(limit));
            EnsureArg.IsGte(offset, 0, nameof(offset));

            var results = new List <ExtendedQueryTagStoreJoinEntry>();

            using (SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken))
                using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand())
                {
                    VLatest.GetExtendedQueryTags.PopulateCommand(sqlCommandWrapper, limit, offset);

                    var executionTimeWatch = Stopwatch.StartNew();
                    using (var reader = await sqlCommandWrapper.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken))
                    {
                        while (await reader.ReadAsync(cancellationToken))
                        {
                            (int tagKey, string tagPath, string tagVR, string tagPrivateCreator, int tagLevel, int tagStatus, byte queryStatus, int errorCount, Guid? operationId) = reader.ReadRow(
                                VLatest.ExtendedQueryTag.TagKey,
                                VLatest.ExtendedQueryTag.TagPath,
                                VLatest.ExtendedQueryTag.TagVR,
                                VLatest.ExtendedQueryTag.TagPrivateCreator,
                                VLatest.ExtendedQueryTag.TagLevel,
                                VLatest.ExtendedQueryTag.TagStatus,
                                VLatest.ExtendedQueryTag.QueryStatus,
                                VLatest.ExtendedQueryTag.ErrorCount,
                                VLatest.ExtendedQueryTagOperation.OperationId.AsNullable());

                            results.Add(new ExtendedQueryTagStoreJoinEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, (QueryStatus)queryStatus, errorCount, operationId));
                        }

                        executionTimeWatch.Stop();
                        Logger.StoredProcedureSucceeded(nameof(VLatest.GetExtendedQueryTags), executionTimeWatch);
                    }
                }

            return(results);
        }
示例#11
0
        ///<inheritdoc/>
        public override async Task <ExtendedQueryTagStoreJoinEntry> UpdateQueryStatusAsync(string tagPath, QueryStatus queryStatus, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNullOrWhiteSpace(tagPath, nameof(tagPath));
            EnsureArg.EnumIsDefined(queryStatus, nameof(queryStatus));

            using SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken);

            using SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand();

            VLatest.UpdateExtendedQueryTagQueryStatus.PopulateCommand(sqlCommandWrapper, tagPath, (byte)queryStatus);

            try
            {
                using SqlDataReader reader = await sqlCommandWrapper.ExecuteReaderAsync(cancellationToken);

                if (!await reader.ReadAsync(cancellationToken))
                {
                    throw new ExtendedQueryTagNotFoundException(string.Format(CultureInfo.InvariantCulture, DicomSqlServerResource.ExtendedQueryTagNotFound, tagPath));
                }

                (int rTagKey, string rTagPath, string rTagVR, string rTagPrivateCreator, byte rTagLevel, byte rTagStatus, byte rQueryStatus, int errorCount, Guid? operationId) = reader.ReadRow(
                    VLatest.ExtendedQueryTag.TagKey,
                    VLatest.ExtendedQueryTag.TagPath,
                    VLatest.ExtendedQueryTag.TagVR,
                    VLatest.ExtendedQueryTag.TagPrivateCreator,
                    VLatest.ExtendedQueryTag.TagLevel,
                    VLatest.ExtendedQueryTag.TagStatus,
                    VLatest.ExtendedQueryTag.QueryStatus,
                    VLatest.ExtendedQueryTag.ErrorCount,
                    VLatest.ExtendedQueryTagOperation.OperationId.AsNullable());

                return(new ExtendedQueryTagStoreJoinEntry(rTagKey, rTagPath, rTagVR, rTagPrivateCreator, (QueryTagLevel)rTagLevel, (ExtendedQueryTagStatus)rTagStatus, (QueryStatus)rQueryStatus, errorCount, operationId));
            }
            catch (SqlException ex)
            {
                throw new DataStoreException(ex);
            }
        }
示例#12
0
        public override async Task <IReadOnlyList <ExtendedQueryTagStoreJoinEntry> > GetExtendedQueryTagsAsync(IReadOnlyCollection <int> queryTagKeys, CancellationToken cancellationToken = default)
        {
            EnsureArg.HasItems(queryTagKeys, nameof(queryTagKeys));

            var results = new List <ExtendedQueryTagStoreJoinEntry>();

            using (SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken))
                using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand())
                {
                    IEnumerable <ExtendedQueryTagKeyTableTypeV1Row> rows = queryTagKeys.Select(x => new ExtendedQueryTagKeyTableTypeV1Row(x));
                    VLatest.GetExtendedQueryTagsByKey.PopulateCommand(sqlCommandWrapper, rows);

                    var executionTimeWatch = Stopwatch.StartNew();
                    using (var reader = await sqlCommandWrapper.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken))
                    {
                        while (await reader.ReadAsync(cancellationToken))
                        {
                            (int tagKey, string tagPath, string tagVR, string tagPrivateCreator, int tagLevel, int tagStatus, byte queryStatus, int errorCount, Guid? operationId) = reader.ReadRow(
                                VLatest.ExtendedQueryTag.TagKey,
                                VLatest.ExtendedQueryTag.TagPath,
                                VLatest.ExtendedQueryTag.TagVR,
                                VLatest.ExtendedQueryTag.TagPrivateCreator,
                                VLatest.ExtendedQueryTag.TagLevel,
                                VLatest.ExtendedQueryTag.TagStatus,
                                VLatest.ExtendedQueryTag.QueryStatus,
                                VLatest.ExtendedQueryTag.ErrorCount,
                                VLatest.ExtendedQueryTagOperation.OperationId.AsNullable());

                            results.Add(new ExtendedQueryTagStoreJoinEntry(tagKey, tagPath, tagVR, tagPrivateCreator, (QueryTagLevel)tagLevel, (ExtendedQueryTagStatus)tagStatus, (QueryStatus)queryStatus, errorCount, operationId));
                        }

                        executionTimeWatch.Stop();
                        Logger.StoredProcedureSucceeded(nameof(VLatest.GetExtendedQueryTagsByKey), executionTimeWatch);
                    }
                }

            return(results);
        }
示例#13
0
        public override async Task <IReadOnlyList <ExtendedQueryTagStoreEntry> > AddExtendedQueryTagsAsync(
            IReadOnlyCollection <AddExtendedQueryTagEntry> extendedQueryTagEntries,
            int maxCount,
            bool ready = false,
            CancellationToken cancellationToken = default)
        {
            if (ready)
            {
                throw new BadRequestException(DicomSqlServerResource.SchemaVersionNeedsToBeUpgraded);
            }

            using (SqlConnectionWrapper sqlConnectionWrapper = await ConnectionWrapperFactory.ObtainSqlConnectionWrapperAsync(cancellationToken))
                using (SqlCommandWrapper sqlCommandWrapper = sqlConnectionWrapper.CreateSqlCommand())
                {
                    IEnumerable <AddExtendedQueryTagsInputTableTypeV1Row> rows = extendedQueryTagEntries.Select(ToAddExtendedQueryTagsInputTableTypeV1Row);

                    V2.AddExtendedQueryTags.PopulateCommand(sqlCommandWrapper, new V2.AddExtendedQueryTagsTableValuedParameters(rows));

                    try
                    {
                        await sqlCommandWrapper.ExecuteNonQueryAsync(cancellationToken);

                        var allTags = (await GetAllExtendedQueryTagsAsync(cancellationToken)).ToDictionary(x => x.Path);

                        return(extendedQueryTagEntries
                               .Select(x => allTags[x.Path])
                               .ToList());
                    }
                    catch (SqlException ex)
                    {
                        throw ex.Number switch
                              {
                                  SqlErrorCodes.Conflict => new ExtendedQueryTagsAlreadyExistsException(),
                                  _ => new DataStoreException(ex),
                              };
                    }
                }
        }