0

我正在尝试编写一个通用方法,例如:

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;
        }
    }

但我无法弄清楚我应该输入什么GetValue(???)。有什么帮助吗?

4

1 回答 1

3

虽然您可以按照您的方式使其工作,但您会发现 Entity Framework Core 无法解析反射代码,这意味着它将FirstOrDefaultAsync在内存中运行。因此,如果您有一个包含 1000 行的表,则所有这些行都将从数据库中提取并在那里过滤。有几个解决方案:

  1. 使用DbSet.Find方法,这看起来就像你想要实现的那样。例如:

    var entity = await _db.Set<TU>().FindAsync(id)
    
  2. 让您的实体实现一个通用接口,例如:

    public interface IEntity
    {
        int Id { get; }
    }
    

    这意味着您的实体将如下所示:

    public class SomeEntity : IEntity
    {
        public int Id { get; set; }
    }
    

    最后,您的方法现在看起来要简单得多:

    protected async Task<ResultModel<TU>> GetEntityByIdAsync<TU, TKey>(TKey id)
        where TU : IEntity
    {
        return await _db.Set<TU>.FirstOrDefaultAsync(x => x.Id == id);
    }
    
  3. 手动构建表达式。这涉及更多,我不打算展示如何做到这一点,因为在这种情况下几乎肯定不需要它。

于 2018-11-30T14:30:58.817 回答