I'm using image sharper to process images and then save in database currently I have the logic in ImageService in the service layer:
private async Task Processor(ImageInputModel image)
{
using var imageResult = await Image.LoadAsync(image.Content);
var original = await SaveImage(imageResult, imageResult.Width);
var thumbnail = await SaveImage(imageResult, ThumbnailWidth);
var articlePreview = await SaveImage(imageResult, ArticlePreviewWidth);
var articleFullscreen = await SaveImage(imageResult, ArticleFullscreenWidth);
var dbContext = _serviceFactory
.CreateScope()
.ServiceProvider
.GetRequiredService<ApplicationDbContext>();
var imageModel = new ImageData
{
OriginalFileName = image.Name,
OriginalType = image.Type,
OriginalContent = original,
ThumbnailContent = thumbnail,
ArticlePreviewContent = articlePreview,
ArticleFullscreenContent = articleFullscreen,
ArticleId = image.ArticleId,
ProjectDataId = image.ProjectId
};
await dbContext.Images.AddAsync(imageModel);
await dbContext.SaveChangesAsync();
}
private async Task<Stream> GetImageData(string id, string size)
{
var database = _dbContext.Database;
var dbConnection = (SqlConnection)database.GetDbConnection();
var command = new SqlCommand(
$"SELECT {size}Content FROM Images WHERE Id = @id",
dbConnection
);
command.Parameters.Add(new SqlParameter("@id", id));
await dbConnection.OpenAsync();
var reader = await command.ExecuteReaderAsync();
Stream result = null;
if (reader.HasRows)
{
while (await reader.ReadAsync())
{
result = reader.GetStream(0);
}
}
await reader.CloseAsync();
await dbConnection.CloseAsync();
return result;
}
private static async Task<byte[]> SaveImage(Image image, int resizeWidth)
{
var width = image.Width;
var height = image.Height;
if (width > resizeWidth)
{
height = (int)((double)resizeWidth / width * height);
width = resizeWidth;
}
image
.Mutate(i => i
.Resize(new Size(width, height)));
image.Metadata.ExifProfile = null;
var memoryStream = new MemoryStream();
await image.SaveAsJpegAsync(memoryStream, new JpegEncoder
{
Quality = 75
});
return memoryStream.ToArray();
}
Now let's say I am to migrate this project to DDD design or start over where do I put this logic? I thought maybe I have a domain model Image and put this logic there but then I think it does not make sense because the Image is for many other domain models it's not a separate entity that domain experts will ask. So maybe I put in value object or domain service but I do not know? Any ideas?
I would (so as always with architecture - its opinion based) say that image is not an entity, but a value object in this case,
therefore it belongs in Domain.
Processing is a service for the image, so infrastructure - service takes image as parameter.
Aggregate root of something that contains image can do something with it, with usage of domain service or service injected into aggregate (interface in domain).
Alternatively you could raise an domain event in aggregate containing image object, and handler of this event would do the processing.