【问题标题】:Select specific columns in a generic repository function在通用存储库函数中选择特定列
【发布时间】:2017-11-28 03:12:19
【问题描述】:

我们想创建一个通用函数,它只选择需要的列而不是返回整个实体。例如,我有一个 Country 类 具有以下属性。

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CountryId { get; set; }
[Required]
public string Name { get; set; }
public int CreatedBy {get;set;}
public DateTime CreatedDate {get;set;}

我有一个所有实体都通用的呼吸类。

public class Repository<T> : IRepository<T> where T : class
{
    DbContext db;
    DbSet<T> currentEntity;
    public Repository(DbContext db)
    {
        this.db = db;
        currentEntity = db.Set<T>();
    }
    public void Add(T TEntity)
    {
        currentEntity.Add(TEntity);
    } 


    public virtual List<T> GetAll()
    {
        return currentEntity.ToList<T>();
    }
}

由于GetAll 方法返回所有列,但我只想选择Name 和CountryId。如何创建一个只返回所需数据的通用函数?

【问题讨论】:

  • 在 C# 中,这意味着您必须从存储库中返回匿名类型或动态类型。我不认为你应该想要那个,是吗?返回IQueryable&lt;T&gt; 而不是List&lt;T&gt; 可能会更好,这样消费者就可以有效地应用预测。
  • 是的,我想从我的存储库中返回动态类型。我可以使用像 Action 这样的通用委托并将其传递给 Linq 的 Select 方法来创建一个匿名类型对象,该对象将只包含国家实体的两个属性。

标签: c# linq repository-pattern


【解决方案1】:

首先您需要在通用存储库中添加通用方法:

public class Repository<T> : IRepository<T> where T : class
{
    DbContext db;
    DbSet<T> currentEntity;
    public Repository(DbContext db)
    {
        this.db = db;
        currentEntity = db.Set<T>();
    }
    public void Add(T TEntity)
    {
        currentEntity.Add(TEntity);
    } 


    public virtual List<T> GetAll()
    {
        return currentEntity.ToList<T>();
    }

    public ICollection<TType> Get<TType>(Expression<Func<T, bool>> where, Expression<Func<T, TType>> select) where TType : class
    {
        return currentEntity.Where(where).Select(select).ToList();
    }
}

现在,你可以调用这个方法了。示例:

public void SomeService()
{
    var myData = Repository.Get(x => x.CountryId > 0, x => new { x.CountryId, x.Name });
    foreach (var item in myData)
    {
        var id = item.CountryId;
        var name = item.Name;
        // ... 
    }
}

最后 - 您需要运行时创建 lambda 表达式和运行时获取必填字段。也许这篇文章对你有帮助:Create a lambda expression with a new anonymous type at runtime,和How do I read an attribute on a class at runtime? p.s.对不起我的英语不好=)

【讨论】:

  • 如果我只想获取例如 Id 列怎么办?我用这个签名创建了方法 public ICollection GetIds(Expression> select) 但是当我写的时候: private static void DoMigrate(ISource sourceService, Idestination destinationService, IParser parser) where T : class where R : class { ... List addedIds = destinationService.GetIds(x => x.Id); ... } 我得到“R 不包含 Id 的定义”
  • 也许您需要写 '{ .. where R: HasId }' 而不是 '{ .. where R: class}',其中 HasId - 具有 Id 属性的类,并且您还需要使用从 HasId 继承目标类
  • 对!在阅读了很多关于它的选项后,我已经采取了
【解决方案2】:

声明一个 DTO 类:

public class Getdata
{
    public int Id { get; set; }
    public string Name { get; set; }
}

然后像这样使用..

public virtual List<Getdata> GetAll()
{
    var countrys = db.currentEntity.ToList();
    var data = (from f in countrys
                select new Getdata
                {
                    Id = f.CountryId,
                    Name = f.CountryName
                 }).ToList();
    return data;
}

【讨论】:

    猜你喜欢
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-01
    • 2013-10-27
    相关资源
    最近更新 更多