I created simply database service with get, insert, get all image names and verify exist method.
All images will be store in blob storage with unique filename + postfix size. Next one I have image model, with simple expression for mapping object select, methods for detection Webp format and existing.
All methods:
GetAllImageNames()
- return enumerable list ofimageNames
Insert(string filename)
- insert filenamesite GetImage(string filename)
- return image entity, mapped toImageModel ImageExist(string filename)
- return true/falseDelete(string filename)
- delete file by filename
I wrote the Image
object entity that represents a database object:
public class Image
{
public int Id { get; set; }
public string Filename { get; set; }
}
This is a very simple entity, no comments are needed I think.
ImageModel
(object result structure):
public class ImageModel
{
public string Filename { get; set; }
public ImageSize Size { get; set; }
public static Expression<Func<Image, ImageModel>> ToModel()
{
return image => new ImageModel
{
Filename = image.Filename,
Size = image.Size
};
}
public bool Exists()
{
return !string.IsNullOrEmpty(Filename);
}
public bool IsWebp()
{
//Now implement for now
}
}
This model class is very simply again:
ToModel()
is a function for mapping to results data.
And finally DatabaseImageService
:
public interface IImageDatabaseService : IRepository<Image>
{
Task<IEnumerable<string>> GetAllImageNames();
Task Insert(string filename);
Task Delete(string filename);
Task<ImageModel> GetImage(string filename);
Task<bool> ImageExist(string filename);
}
IRepository
is design pattern Repository for manipulation with database operations. It's possible to use it as DI of course. But I like to use it as an inherit interface of the current entity.
public class ImageDatabaseService : Repository<Image>, IImageDatabaseService
{
public ImageDatabaseService(DbContext dbContext, IUnityOfWork unityOfWork) : base(dbContext)
{
this.UnityOfWork = unityOfWork;
}
private IUnityOfWork UnityOfWork { get; set; }
public async Task<IEnumerable<string>> GetAllImageNames()
{
return await this.Select(s => s.Filename).ToListAsync();
}
public async Task Insert(string filename)
{
this.InsertAsBatch(filename);
await this.UnityOfWork.SaveAsync();
}
public async Task Delete(string filename)
{
var image = await this.FirstOrDefaultAsync(s =>
s.Filename.Equals(filename, StringComparison.InvariantCultureIgnoreCase));
if (image != null)
{
this.Remove(image);
await this.UnityOfWork.SaveAsync();
}
}
public async Task<bool> ImageExist(string filename)
{
var image = await GetImage(filename);
return image.Exists();
}
public async Task<ImageModel> GetImage(string filename)
{
return await this.Where(s => s.Filename.Equals(filename, StringComparison.InvariantCultureIgnoreCase))
.Select(ImageModel.ToModel()).FirstOrDefaultAsync();
}
private void InsertAsBatch(string filename)
{
var image = this.Create();
image.Filename = filename;
//possibly another image attributes
this.Add(image);
}
}
UnityOfWork
is a design pattern for saving data to my database, used in combination with the Repository pattern.