示例#1
0
        public async Task InsertBinaryPropertyWithFileIdAsync(BinaryDataValue value, int versionId, int propertyTypeId, bool isNewNode,
                                                              SnDataContext dataContext)
        {
            var sql = isNewNode ? InsertBinaryPropertyWithKnownFileIdScript : DeleteAndInsertBinaryPropertyWithKnownFileIdScript;

            if (!isNewNode)
            {
                dataContext.NeedToCleanupFiles = true;
            }

            if (!(dataContext is MsSqlDataContext sqlCtx))
            {
                throw new PlatformNotSupportedException();
            }

            value.Id = (int)await sqlCtx.ExecuteScalarAsync(sql, cmd =>
            {
                cmd.Parameters.AddRange(new[]
                {
                    sqlCtx.CreateParameter("@VersionId", DbType.Int32, versionId != 0 ? (object)versionId : DBNull.Value),
                    sqlCtx.CreateParameter("@PropertyTypeId", DbType.Int32, propertyTypeId != 0 ? (object)propertyTypeId : DBNull.Value),
                    sqlCtx.CreateParameter("@FileId", DbType.Int32, value.FileId),
                });
            }).ConfigureAwait(false);
        }
示例#2
0
        public void DC_Dispose()
        {
            SnDataContext   dataContext     = null;
            TestConnection  testConnection  = null;
            TestTransaction testTransaction = null;

            try
            {
                using (dataContext = new TestDataContext(CancellationToken.None))
                {
                    Assert.IsFalse(dataContext.IsDisposed);
                    using (var transaction = dataContext.BeginTransaction(IsolationLevel.ReadCommitted, TimeSpan.FromMinutes(10)))
                    {
                        testConnection  = (TestConnection)dataContext.Connection;
                        testTransaction = (TestTransaction)dataContext.Transaction.Transaction;
                        throw new SnNotSupportedException();
                    }
                }
            }
            catch (SnNotSupportedException)
            {
                // do nothing
            }
            Assert.IsTrue(testConnection.State == ConnectionState.Closed);
            Assert.IsTrue(testTransaction.IsRollbackCalled);
            Assert.IsTrue(dataContext.IsDisposed);
        }
示例#3
0
        internal static void DropPackagesTable(SnDataContext ctx)
        {
            var sql = @"
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Packages]') AND type in (N'U'))
DROP TABLE [dbo].[Packages]
";

            ctx.ExecuteNonQueryAsync(sql).GetAwaiter().GetResult();
        }
        public STT.Task InsertBinaryPropertyAsync(IBlobProvider blobProvider, BinaryDataValue value, int versionId, int propertyTypeId,
                                                  bool isNewNode, SnDataContext dataContext)
        {
            var streamLength = value.Stream?.Length ?? 0;
            var ctx          = new BlobStorageContext(blobProvider)
            {
                VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = streamLength
            };

            // blob operation

            blobProvider.AllocateAsync(ctx, CancellationToken.None).GetAwaiter().GetResult();

            using (var stream = blobProvider.GetStreamForWrite(ctx))
                value.Stream?.CopyTo(stream);

            value.BlobProviderName = ctx.Provider.GetType().FullName;
            value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData);

            // metadata operation
            var db = DataProvider.DB;

            if (!isNewNode)
            {
                DeleteBinaryPropertyAsync(versionId, propertyTypeId, dataContext).GetAwaiter().GetResult();
            }

            var fileId = db.Files.GetNextId();

            db.Files.Insert(new FileDoc
            {
                FileId      = fileId,
                ContentType = value.ContentType,
                Extension   = value.FileName.Extension,
                FileNameWithoutExtension = value.FileName.FileNameWithoutExtension,
                Size             = Math.Max(0, value.Size),
                BlobProvider     = value.BlobProviderName,
                BlobProviderData = value.BlobProviderData
            });
            var binaryPropertyId = db.BinaryProperties.GetNextId();

            db.BinaryProperties.Insert(new BinaryPropertyDoc
            {
                BinaryPropertyId = binaryPropertyId,
                FileId           = fileId,
                PropertyTypeId   = propertyTypeId,
                VersionId        = versionId
            });

            value.Id        = binaryPropertyId;
            value.FileId    = fileId;
            value.Timestamp = 0L; //TODO: file row timestamp

            return(STT.Task.CompletedTask);
        }
        public STT.Task DeleteBinaryPropertiesAsync(IEnumerable <int> versionIds, SnDataContext dataContext)
        {
            var db = DataProvider.DB;

            foreach (var item in db.BinaryProperties
                     .Where(x => versionIds.Contains(x.VersionId))
                     .ToArray())
            {
                db.BinaryProperties.Remove(item);
            }
            return(STT.Task.CompletedTask);
        }
        public STT.Task DeleteBinaryPropertyAsync(int versionId, int propertyTypeId, SnDataContext dataContext)
        {
            var db = DataProvider.DB;

            foreach (var item in db.BinaryProperties
                     .Where(x => x.VersionId == versionId && x.PropertyTypeId == propertyTypeId)
                     .ToArray())
            {
                db.BinaryProperties.Remove(item);
            }
            return(STT.Task.CompletedTask);
        }
示例#7
0
        public async Task DeleteBinaryPropertiesAsync(IEnumerable <int> versionIds, SnDataContext dataContext)
        {
            if (!(dataContext is MsSqlDataContext sqlCtx))
            {
                throw new PlatformNotSupportedException();
            }

            await sqlCtx.ExecuteNonQueryAsync(DeleteBinaryPropertiesScript, cmd =>
            {
                var idsParam = string.Join(",", versionIds.Select(x => x.ToString()));
                cmd.Parameters.Add(sqlCtx.CreateParameter("@VersionIds", DbType.String, idsParam.Length, idsParam));
            }).ConfigureAwait(false);
        }
示例#8
0
        internal static void InstallPackagesTable(SnDataContext ctx)
        {
            var sql = @"
CREATE TABLE [dbo].[Packages](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [PackageType] [varchar](50) NOT NULL,
    [ComponentId] [nvarchar](450) NULL,
    [ComponentVersion] [varchar](50) NULL,
    [ReleaseDate] [datetime2](7) NOT NULL,
    [ExecutionDate] [datetime2](7) NOT NULL,
    [ExecutionResult] [varchar](50) NOT NULL,
    [ExecutionError] [nvarchar](max) NULL,
    [Description] [nvarchar](1000) NULL,
    [Manifest] [nvarchar](max) NULL,
 CONSTRAINT [PK_Packages] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
";

            ctx.ExecuteNonQueryAsync(sql).GetAwaiter().GetResult();
        }
        public STT.Task InsertBinaryPropertyWithFileIdAsync(BinaryDataValue value, int versionId, int propertyTypeId, bool isNewNode,
                                                            SnDataContext dataContext)
        {
            var db = DataProvider.DB;

            if (!isNewNode)
            {
                DeleteBinaryPropertyAsync(versionId, propertyTypeId, dataContext).GetAwaiter().GetResult();
            }

            var binaryPropertyId = db.BinaryProperties.GetNextId();

            db.BinaryProperties.Insert(new BinaryPropertyDoc
            {
                BinaryPropertyId = binaryPropertyId,
                FileId           = value.FileId,
                PropertyTypeId   = propertyTypeId,
                VersionId        = versionId
            });

            value.Id = binaryPropertyId;

            return(STT.Task.CompletedTask);
        }
示例#10
0
        public async Task <BinaryCacheEntity> LoadBinaryCacheEntityAsync(int versionId, int propertyTypeId, SnDataContext dataContext)
        {
            if (!(dataContext is MsSqlDataContext sqlCtx))
            {
                throw new PlatformNotSupportedException();
            }

            return(await sqlCtx.ExecuteReaderAsync(LoadBinaryCacheEntityScript, cmd =>
            {
                cmd.Parameters.AddRange(new[]
                {
                    sqlCtx.CreateParameter("@MaxSize", DbType.Int32, BlobStorageOptions.BinaryCacheSize),
                    sqlCtx.CreateParameter("@VersionId", DbType.Int32, versionId),
                    sqlCtx.CreateParameter("@PropertyTypeId", DbType.Int32, propertyTypeId),
                });
            }, async (reader, cancel) =>
            {
                cancel.ThrowIfCancellationRequested();
                if (!reader.HasRows || !await reader.ReadAsync(cancel).ConfigureAwait(false))
                {
                    return null;
                }

                var length = reader.GetInt64(0);
                var binaryPropertyId = reader.GetInt32(1);
                var fileId = reader.GetInt32(2);

                var providerName = reader.GetSafeString(3);
                var providerTextData = reader.GetSafeString(4);

                byte[] rawData = null;

                var provider = Providers.GetProvider(providerName);
                var context = new BlobStorageContext(provider, providerTextData)
                {
                    VersionId = versionId,
                    PropertyTypeId = propertyTypeId,
                    FileId = fileId,
                    Length = length
                };
                if (provider is IBuiltInBlobProvider)
                {
                    context.BlobProviderData = new BuiltinBlobProviderData();
                    if (!reader.IsDBNull(5))
                    {
                        rawData = (byte[])reader.GetValue(5);
                    }
                }

                return new BinaryCacheEntity
                {
                    Length = length,
                    RawData = rawData,
                    BinaryPropertyId = binaryPropertyId,
                    FileId = fileId,
                    Context = context
                };
            }).ConfigureAwait(false));
        }
        public Task <BinaryCacheEntity> LoadBinaryCacheEntityAsync(int versionId, int propertyTypeId, SnDataContext dataContext)
        {
            var db        = DataProvider.DB;
            var binaryDoc =
                db.BinaryProperties.FirstOrDefault(r => r.VersionId == versionId && r.PropertyTypeId == propertyTypeId);

            if (binaryDoc == null)
            {
                return(null);
            }

            var fileDoc = db.Files.FirstOrDefault(x => x.FileId == binaryDoc.FileId);

            if (fileDoc == null)
            {
                return(null);
            }
            if (fileDoc.Staging)
            {
                return(null);
            }

            var length           = fileDoc.Size;
            var binaryPropertyId = binaryDoc.BinaryPropertyId;
            var fileId           = fileDoc.FileId;

            var providerName     = fileDoc.BlobProvider;
            var providerTextData = fileDoc.BlobProviderData;

            var rawData = fileDoc.Buffer;

            var provider = BlobStorageBase.GetProvider(providerName);
            var context  = new BlobStorageContext(provider, providerTextData)
            {
                VersionId      = versionId,
                PropertyTypeId = propertyTypeId,
                FileId         = fileId,
                Length         = length,
            };

            var result = new BinaryCacheEntity
            {
                Length           = length,
                RawData          = rawData,
                BinaryPropertyId = binaryPropertyId,
                FileId           = fileId,
                Context          = context
            };

            return(STT.Task.FromResult(result));
        }
        public Task <BinaryDataValue> LoadBinaryPropertyAsync(int versionId, int propertyTypeId, SnDataContext dataContext)
        {
            var db = DataProvider.DB;

            BinaryDataValue result = null;

            var binaryDoc = db.BinaryProperties.FirstOrDefault(x =>
                                                               x.VersionId == versionId && x.PropertyTypeId == propertyTypeId);

            if (binaryDoc == null)
            {
                return(STT.Task.FromResult(result));
            }

            var fileDoc = db.Files.FirstOrDefault(x => x.FileId == binaryDoc.FileId);

            if (fileDoc == null)
            {
                return(STT.Task.FromResult(result));
            }
            if (fileDoc.Staging)
            {
                return(STT.Task.FromResult(result));
            }

            result = CreateBinaryDataValue(db, binaryDoc, fileDoc);
            return(STT.Task.FromResult(result));
        }
        public STT.Task UpdateBinaryPropertyAsync(IBlobProvider blobProvider, BinaryDataValue value, SnDataContext dataContext)
        {
            var streamLength = value.Stream?.Length ?? 0;
            var isExternal   = false;

            if (streamLength > 0)
            {
                // BlobProviderData parameter is irrelevant because it will be overridden in the Allocate method
                var ctx = new BlobStorageContext(blobProvider)
                {
                    VersionId      = 0,
                    PropertyTypeId = 0,
                    FileId         = value.FileId,
                    Length         = streamLength,
                };

                blobProvider.AllocateAsync(ctx, CancellationToken.None).GetAwaiter().GetResult();
                isExternal = true;

                value.BlobProviderName = ctx.Provider.GetType().FullName;
                value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData);
            }

            var isRepositoryStream = value.Stream is RepositoryStream;
            var hasStream          = isRepositoryStream || value.Stream is MemoryStream;

            if (!isExternal && !hasStream)
            {
                // do not do any database operation if the stream is not modified
                return(STT.Task.CompletedTask);
            }

            var db     = DataProvider.DB;
            var fileId = db.Files.GetNextId();

            db.Files.Insert(new FileDoc
            {
                FileId      = fileId,
                ContentType = value.ContentType,
                Extension   = value.FileName.Extension,
                FileNameWithoutExtension = value.FileName.FileNameWithoutExtension,
                Size             = Math.Max(0, value.Size),
                BlobProvider     = value.BlobProviderName,
                BlobProviderData = value.BlobProviderData
            });
            var binaryPropertyDoc = db.BinaryProperties.FirstOrDefault(x => x.BinaryPropertyId == value.Id);

            if (binaryPropertyDoc != null)
            {
                binaryPropertyDoc.FileId = fileId;
            }

            if (fileId > 0 && fileId != value.FileId)
            {
                value.FileId = fileId;
            }

            // update stream with a new context
            var newCtx = new BlobStorageContext(blobProvider, value.BlobProviderData)
            {
                VersionId      = 0,
                PropertyTypeId = 0,
                FileId         = value.FileId,
                Length         = streamLength,
            };

            using (var stream = blobProvider.GetStreamForWrite(newCtx))
                value.Stream?.CopyTo(stream);

            return(STT.Task.CompletedTask);
        }
示例#14
0
        public async Task InsertBinaryPropertyAsync(IBlobProvider blobProvider, BinaryDataValue value, int versionId, int propertyTypeId,
                                                    bool isNewNode, SnDataContext dataContext)
        {
            var streamLength = value.Stream?.Length ?? 0;
            var ctx          = new BlobStorageContext(blobProvider)
            {
                VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = streamLength
            };

            // In case of an external provider allocate the place for bytes and
            // write the stream beforehand and get the generated provider data.
            // Note that the external provider does not need an existing record
            // in the Files table to work, it just stores the bytes.
            if (!(blobProvider is IBuiltInBlobProvider))
            {
                await blobProvider.AllocateAsync(ctx, dataContext.CancellationToken).ConfigureAwait(false);

                using (var stream = blobProvider.GetStreamForWrite(ctx))
                    value.Stream?.CopyTo(stream);

                value.BlobProviderName = ctx.Provider.GetType().FullName;
                value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData);
            }

            if (!(dataContext is MsSqlDataContext sqlCtx))
            {
                throw new PlatformNotSupportedException();
            }

            var sql = isNewNode ? InsertBinaryPropertyScript : DeleteAndInsertBinaryPropertyScript;

            if (!isNewNode)
            {
                dataContext.NeedToCleanupFiles = true;
            }

            await sqlCtx.ExecuteReaderAsync(sql, cmd =>
            {
                cmd.Parameters.AddRange(new[]
                {
                    sqlCtx.CreateParameter("@VersionId", DbType.Int32, versionId != 0 ? (object)versionId : DBNull.Value),
                    sqlCtx.CreateParameter("@PropertyTypeId", DbType.Int32, propertyTypeId != 0 ? (object)propertyTypeId : DBNull.Value),
                    sqlCtx.CreateParameter("@ContentType", DbType.String, 450, value.ContentType),
                    sqlCtx.CreateParameter("@FileNameWithoutExtension", DbType.String, 450, value.FileName.FileNameWithoutExtension == null ? DBNull.Value : (object)value.FileName.FileNameWithoutExtension),
                    sqlCtx.CreateParameter("@Extension", DbType.String, 50, ValidateExtension(value.FileName.Extension)),
                    sqlCtx.CreateParameter("@Size", DbType.Int64, Math.Max(0, value.Size)),
                    sqlCtx.CreateParameter("@BlobProvider", DbType.String, 450, value.BlobProviderName != null ? (object)value.BlobProviderName : DBNull.Value),
                    sqlCtx.CreateParameter("@BlobProviderData", DbType.String, int.MaxValue, value.BlobProviderData != null ? (object)value.BlobProviderData : DBNull.Value),
                    sqlCtx.CreateParameter("@Checksum", DbType.AnsiString, 200, value.Checksum != null ? (object)value.Checksum : DBNull.Value),
                });
            }, async (reader, cancel) =>
            {
                if (await reader.ReadAsync(cancel).ConfigureAwait(false))
                {
                    value.Id        = Convert.ToInt32(reader[0]);
                    value.FileId    = Convert.ToInt32(reader[1]);
                    value.Timestamp = Utility.Convert.BytesToLong((byte[])reader.GetValue(2));
                }
                return(true);
            }).ConfigureAwait(false);

            // The BuiltIn blob provider saves the stream after the record
            // was saved into the Files table, because simple varbinary
            // column must exist before we can write a stream into the record.
            // ReSharper disable once InvertIf
            if (blobProvider is IBuiltInBlobProvider && value.Stream != null)
            {
                ctx.FileId           = value.FileId;
                ctx.BlobProviderData = new BuiltinBlobProviderData();

                await BuiltInBlobProvider.AddStreamAsync(ctx, value.Stream, sqlCtx).ConfigureAwait(false);
            }
        }
示例#15
0
        public async Task <BinaryDataValue> LoadBinaryPropertyAsync(int versionId, int propertyTypeId, SnDataContext dataContext)
        {
            if (!(dataContext is MsSqlDataContext sqlCtx))
            {
                throw new PlatformNotSupportedException();
            }

            return(await sqlCtx.ExecuteReaderAsync(LoadBinaryPropertyScript, cmd =>
            {
                cmd.Parameters.AddRange(new[]
                {
                    sqlCtx.CreateParameter("@VersionId", DbType.Int32, versionId),
                    sqlCtx.CreateParameter("@PropertyTypeId", DbType.Int32, propertyTypeId),
                });
            }, async (reader, cancel) =>
            {
                cancel.ThrowIfCancellationRequested();
                if (!await reader.ReadAsync(cancel).ConfigureAwait(false))
                {
                    return null;
                }

                var size = reader.GetInt64("Size");
                var binaryPropertyId = reader.GetInt32("BinaryPropertyId");
                var fileId = reader.GetInt32("FileId");
                var providerName = reader.GetSafeString("BlobProvider");
                var providerTextData = reader.GetSafeString("BlobProviderData");
                var provider = Providers.GetProvider(providerName);
                var context = new BlobStorageContext(provider, providerTextData)
                {
                    VersionId = versionId,
                    PropertyTypeId = propertyTypeId,
                    FileId = fileId,
                    Length = size
                };
                Stream stream = null;
                if (provider is IBuiltInBlobProvider)
                {
                    context.BlobProviderData = new BuiltinBlobProviderData();
                    var streamIndex = reader.GetOrdinal("Stream");
                    if (!reader.IsDBNull(streamIndex))
                    {
                        var rawData = (byte[])reader.GetValue(streamIndex);
                        stream = new MemoryStream(rawData);
                    }
                }

                return new BinaryDataValue
                {
                    Id = binaryPropertyId,
                    FileId = fileId,
                    ContentType = reader.GetSafeString("ContentType"),
                    FileName = new BinaryFileName(
                        reader.GetSafeString("FileNameWithoutExtension") ?? "",
                        reader.GetSafeString("Extension") ?? ""),
                    Size = size,
                    Checksum = reader.GetSafeString("Checksum"),
                    BlobProviderName = providerName,
                    BlobProviderData = providerTextData,
                    Timestamp = reader.GetSafeLongFromBytes("Timestamp"),
                    Stream = stream
                };
            }).ConfigureAwait(false));
        }
示例#16
0
        public async Task DeleteBinaryPropertyAsync(int versionId, int propertyTypeId, SnDataContext dataContext)
        {
            if (!(dataContext is MsSqlDataContext sqlCtx))
            {
                throw new PlatformNotSupportedException();
            }

            await sqlCtx.ExecuteNonQueryAsync(DeleteBinaryPropertyScript, cmd =>
            {
                cmd.Parameters.AddRange(new[]
                {
                    sqlCtx.CreateParameter("@VersionId", DbType.Int32, versionId),
                    sqlCtx.CreateParameter("@PropertyTypeId", DbType.Int32, propertyTypeId),
                });
            }).ConfigureAwait(false);
        }
示例#17
0
        public async Task UpdateBinaryPropertyAsync(IBlobProvider blobProvider, BinaryDataValue value, SnDataContext dataContext)
        {
            var streamLength = value.Stream?.Length ?? 0;
            var isExternal   = false;

            if (!(blobProvider is IBuiltInBlobProvider))
            {
                // BlobProviderData parameter is irrelevant because it will be overridden in the Allocate method
                var ctx = new BlobStorageContext(blobProvider)
                {
                    VersionId      = 0,
                    PropertyTypeId = 0,
                    FileId         = value.FileId,
                    Length         = streamLength,
                };

                await blobProvider.AllocateAsync(ctx, dataContext.CancellationToken).ConfigureAwait(false);

                isExternal = true;

                value.BlobProviderName = ctx.Provider.GetType().FullName;
                value.BlobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData);
            }
            else
            {
                value.BlobProviderName = null;
                value.BlobProviderData = null;
            }

            if (blobProvider is IBuiltInBlobProvider)
            {
                // MS-SQL does not support stream size over [Int32.MaxValue].
                if (streamLength > int.MaxValue)
                {
                    throw new NotSupportedException();
                }
            }

            var isRepositoryStream = value.Stream is RepositoryStream;
            var hasStream          = isRepositoryStream || value.Stream is MemoryStream;

            if (!isExternal && !hasStream)
            {
                // do not do any database operation if the stream is not modified
                return;
            }

            if (!(dataContext is MsSqlDataContext sqlCtx))
            {
                throw new PlatformNotSupportedException();
            }

            var sql = blobProvider is IBuiltInBlobProvider
                ? UpdateBinaryPropertyScript
                : UpdateBinaryPropertyNewFilerowScript;
            var fileId = (int)await sqlCtx.ExecuteScalarAsync(sql, cmd =>
            {
                cmd.Parameters.AddRange(new[]
                {
                    sqlCtx.CreateParameter("@BinaryPropertyId", DbType.Int32, value.Id),
                    sqlCtx.CreateParameter("@ContentType", DbType.String, 450, value.ContentType),
                    sqlCtx.CreateParameter("@FileNameWithoutExtension", DbType.String, 450, value.FileName.FileNameWithoutExtension == null ? DBNull.Value : (object)value.FileName.FileNameWithoutExtension),
                    sqlCtx.CreateParameter("@Extension", DbType.String, 50, ValidateExtension(value.FileName.Extension)),
                    sqlCtx.CreateParameter("@Size", DbType.Int64, value.Size),
                    sqlCtx.CreateParameter("@Checksum", DbType.AnsiString, 200, value.Checksum != null ? (object)value.Checksum : DBNull.Value),
                    sqlCtx.CreateParameter("@BlobProvider", DbType.String, 450, value.BlobProviderName != null ? (object)value.BlobProviderName : DBNull.Value),
                    sqlCtx.CreateParameter("@BlobProviderData", DbType.String, int.MaxValue, value.BlobProviderData != null ? (object)value.BlobProviderData : DBNull.Value),
                });
            }).ConfigureAwait(false);

            if (fileId > 0 && fileId != value.FileId)
            {
                value.FileId = fileId;
            }

            if (blobProvider is IBuiltInBlobProvider)
            {
                // Stream exists and is loaded -> write it
                var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData)
                {
                    VersionId        = 0,
                    PropertyTypeId   = 0,
                    FileId           = value.FileId,
                    Length           = streamLength,
                    BlobProviderData = new BuiltinBlobProviderData()
                };

                await BuiltInBlobProvider.UpdateStreamAsync(ctx, value.Stream, sqlCtx).ConfigureAwait(false);
            }
            else
            {
                var ctx = new BlobStorageContext(blobProvider, value.BlobProviderData)
                {
                    VersionId      = 0,
                    PropertyTypeId = 0,
                    FileId         = value.FileId,
                    Length         = streamLength,
                };
                if (streamLength == 0)
                {
                    await blobProvider.ClearAsync(ctx, dataContext.CancellationToken).ConfigureAwait(false);
                }
                else
                {
                    using (var stream = blobProvider.GetStreamForWrite(ctx))
                        value.Stream?.CopyTo(stream);
                }
            }
        }