【问题标题】:Using Distinct in generic DbSet queries在通用 DbSet 查询中使用 Distinct
【发布时间】:2021-02-01 13:01:43
【问题描述】:

我正在尝试针对实体框架DbSet 运行 Distinct 查询。这些列表用于填充 UI 中的 Select,以过滤 TRecord 的数据集。下面列出了完整的方法。 fieldNameDbSet 中的字段之一。下面的代码有效,但效率低下。如果您尝试直接在DbSet 上使用Distinct(),它不会做不同的事情 - 只是返回完整的数据集。我假设问题在于我使用反射来获取价值的方式。有解决办法吗?

public async static Task<List<string>> GetDistinctListAsync<TRecord>(this DbContext context, string fieldName) where TRecord : class, IDbRecord<TRecord>, new()
{
     // Get the DbSet for TRecord
     var dbset = GetDbSet<TRecord>(context, null);
     // declare list as an empty list
     var list = new List<string>();
     // Get the filter propertyinfo object
     var x = typeof(TRecord).GetProperty(fieldName);
     if (dbset != null && x != null)
     {
          // we get the full list and then run a distinct because we can't run a distinct directly on the dbSet
          var fulllist = await dbset.Select(item => x.GetValue(item).ToString()).ToListAsync();
          list = fulllist.Distinct().ToList();
     }
     return list ?? new List<string>();
}

我正在修改使用通过DbSet.FromSQLRaw() 调用的 SQL Distinct Query 的旧代码。

【问题讨论】:

  • 您能否包含您要翻译的代码?
  • 效率低下,因为您获取所有内容并在内存中处理它......这个帖子可能会有所帮助:stackoverflow.com/questions/32619338/…
  • 嗨,Alexandru,下面的问题回答了我的问题,所以我不会再麻烦你了。我的生产代码在 DbSet.FromSQLRaw() 上运行,我试图摆脱原始 SQL。

标签: c# entity-framework distinct


【解决方案1】:

需要注意的是,我不知道 GetDbSet&lt;TRecord&gt; 有什么魔力,这里有一个替换函数来处理它,灵感来自: Create generic selector for Select() while using Entity Framework

public static async Task<List<string>> GetDistinctListAsync<TRecord>(this DAL.DbContext context, string fieldName) where TRecord : class
    {
        var dbset = context.Set<TRecord>();

        // Return value.
        List<string> list = null;

        if (dbset != null) // Found matching dbSet
        {
            // Convert our property into a lambda expression.
            var arg = Expression.Parameter(typeof(TRecord), "current");
            var property = Expression.Property(arg, fieldName);
            var conv = Expression.Convert(property, typeof(object));
            var exp = Expression.Lambda<Func<TRecord, object>>(conv, new ParameterExpression[] { arg });

            list = 
                (await dbset.Select(exp).Distinct().ToArrayAsync()) // This runs against database / SQL
                .Select(x => x.ToString()).ToList(); // Convert return values into strings locally if necessary.
        }
        return list ?? new List<string>();
    }

【讨论】:

  • 谢谢,效果很好。只见树木不见森林!
  • 嗨@ShaunCurtis,如果这个或任何答案解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。
  • 完成。你每天都会学到一些新东西!仅供参考,代码是 Blazor 的基于泛型的数据访问层服务的一部分。 GetDbSet 只是从 EF DbContext 中获取正确的 DbSet。
猜你喜欢
  • 1970-01-01
  • 2013-10-01
  • 1970-01-01
  • 2020-12-29
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多