将Linq应用于DbContext中的DbSet

本文关键字:中的 DbSet DbContext 应用于 Linq | 更新日期: 2023-09-27 18:25:22

假设我有一个名为Item的模型,它看起来像这样:

public int ID { get; set; }
public DateTime DateCreated { get; set; }
public DateTime? DateArchived { get; set; }
[Required]
public string Alias { get; set; }

它已包含在DbContext中。。。

public DbSet<Item> Items { get; set; }

每当我想从数据库中选择所有项目时,我只想包括Archived == null和按Alias排序的项目。

当调用DbSet(例如在DbContext上)时,有没有一种方法可以设置EF来执行此操作?

例如,如果我调用db。在控制器中的项,我总是希望应用这些选项,而不必显式地声明它们。

我目前的方法是用前缀"All"重命名DbSet,并添加一个应用了这些选项的函数(函数使用DbSet的原始名称,这样脚手架控制器和页面就可以使用自定义查询,而不需要任何更改):

public DbSet<Item> AllItems { get; set; }
public IQueryable<Item> Items
{
    get { return AllItems.Where(item => item.Archived == null).OrderBy(item  => item.Alias); }
}

但这种方法有些让人觉得很粗糙/错误。这是个好办法吗?这通常应该如何完成?

将Linq应用于DbContext中的DbSet

我曾经遇到过类似的问题,我创建了一个数据库视图来显示我的数据,但有所有必要的限制。视图可以具有与表相同的字段,但不是必须的。然后创建另一个DbSet项,例如DbSet<ItemView>,它在数据库中对应于视图而不是表。在这个视图中,您可以随心所欲地声明where语句。如果属性相同,也可以为两个类创建相同的祖先(例如,ItemItemView都继承自ItemBase)。

我已经在MS SQL Server上完成了这项工作。

我通常避免直接访问DbSet,并通过将上下文隐藏在接口后面来实现这个想法。然后我只从接口访问存储库方法。如果您希望客户端代码不能访问表集合(并希望将其引导到某个已筛选的数据子集),则在客户端代码中使用DbSets时,这将从intelli sense中隐藏DbSets。

public interface IDataContext : IDisposable
{
    void SaveChanges();
    IQueryable<Item> GetItems();
}
public class DataContext : DbContext, IDataContext
{
    public DataContext(string connectionStringName) : base(connectionStringName) { }
    public DbSet<Item> Items { get; set; }
    public IQueryable<Item> GetItems()
    {
        return Items.Where(item => item.Archived == null).OrderBy(item  => item.Alias); 
    }
}
using (IDataContext context = new DataContext("myConnection"))
{
    var items = context.GetItems();
}