Reputation: 149
I'm trying to write a general method like:
protected async Task<ResultModel<TU>> GetEntityByIdAsync<TU, TKey>(TKey id) where TU : class
{
try
{
var result = await _db.Set<TU>().FirstOrDefaultAsync(x =>
x.GetType().GetProperty("Id").GetValue(???).ToString() == id.ToString());
return result.ToResultModel();
}
catch (Exception ex)
{
_logger.Error($"Error In GetEntityByIdAsync {typeof(TU).Name}. Error: {ex}");
throw;
}
}
but I cannot figure it out what should I put in GetValue(???)
.
any help?
Upvotes: 0
Views: 223
Reputation: 119166
While you can get it working as you are trying to do, what you will find is that Entity Framework Core is not able to parse the reflection code, meaning it will run the FirstOrDefaultAsync
in memory. So if you have a table with 1000 rows, all of those rows will be extracted from the database and filtered there. There's a few solutions:
Use the DbSet.Find method, this looks like it will do exactly what you are trying to achieve. For example:
var entity = await _db.Set<TU>().FindAsync(id)
Make your entities implement a common interface, for example:
public interface IEntity
{
int Id { get; }
}
Meaning your entities will look something like this:
public class SomeEntity : IEntity
{
public int Id { get; set; }
}
And finally your method now looks a lot simpler:
protected async Task<ResultModel<TU>> GetEntityByIdAsync<TU, TKey>(TKey id)
where TU : IEntity
{
return await _db.Set<TU>.FirstOrDefaultAsync(x => x.Id == id);
}
Build up an expression manually. This is a lot more involved and I'm not going to show how to do it as it's almost certainly not needed in this situation.
Upvotes: 3