Не работает LINQ запрос, в котором я хочу получить хэшкод объекта с помощью GetHashCode
Мне необходимо сделать одноразовую ссылку на скачивание файла, не знаю насколько это правильно, но я делаю так:
- Переопределяю GetHashCode в классе:
public class StoredFile
{
public int Id { get; set; }
public string FileName { get; set; }
public override int GetHashCode()
{
return HashCode.Combine(FileName, DateTime.Now.ToString("dd.MM.yyyy HH:mm"));
}
}
Генерирую ссылку на основе переданного в GET запрос названия файла, выглядит примерно так -
https://localhost:номер_порта/api/Files/DownloadFile/{file.GetHashCode()}Запрос из 2 пункта обрабатывает метод
GetFileFromDataBase, в котором мне необходимо найти файл, у которого хэш совпадает с тем, который в ссылке; я это делаю так:
var file = dataContext.StoredFiles.Where(f => f.GetHashCode().ToString() == hashCode).FirstOrDefault();
if (file == null) return BadRequest($"The link is invalid");
Когда выполнение кода доходит до поиска файла с помощью LINQ (var file =...) возникает следующая ошибка:
InvalidOperationException: The LINQ expression 'DbSet() .Where(s => s.GetHashCode().ToString() == __hashCode_0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.
Ну вот, не могу понять в чем именно состоит ошибка, нельзя в лямбде использовать получение хэшкода или как-то надо переписать LINQ запрос (видимо да, но как)?
Конечно я могу сделать так и всё будет работать:
StoredFile file = null;
foreach (var item in dataContext.StoredFiles)
{
if (hashCode == item.GetHashCode().ToString())
file = item;
}
if (file == null) return BadRequest($"The link is invalid");
Но хотелось бы сделать с помощью LINQ.
Ответы (1 шт):
public class StoredFile
{
public int Id { get; set; }
public string FileName { get; set; }
[NotMapped]
public String TemporaryFilename
{
get
{
Byte[] str = Encoding.UTF8.GetBytes($"{Id} {FileName}");
String result = Convert.ToBase64String(str);
return result;
}
}
}
var file = dataContext.StoredFiles.AsEnumerable().FirstOrDefault(f => f.TemporaryFilename == hashCode);
Как указали, решение действительно плохое. Тогда как вариант можно использовать MemoryCache как таблицу временных файлов. Там можно будет настроить время хранения файла. https://docs.microsoft.com/en-us/dotnet/api/system.runtime.caching.memorycache. TemporaryFilename - генерировать на основе Id и FileName без доп. атрибутов и загонять в кэш.