假设我有一个名为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时设置EF来执行此操作(例如,在DbContext上)?
例如,如果我在控制器中调用db.Items,我总是希望应用这些选项而不必明确说明它们。
我目前的方法是使用前缀“All”重命名DbSet并添加一个应用了这些选项的函数(函数使用DbSet的原始名称,以便脚手架控制器和页面使用自定义查询而无需任何更改):< / p>
public DbSet<Item> AllItems { get; set; }
public IQueryable<Item> Items
{
get { return AllItems.Where(item => item.Archived == null).OrderBy(item => item.Alias); }
}
但是关于这种方法的一些东西感觉是hackish / wrong。这是一个很好的方法吗?这通常应该如何完成?
答案 0 :(得分:0)
我曾经遇到类似的问题而且我创建了一个数据库视图来显示我的数据以及所有必要的限制。视图可以与表具有相同的字段,但不是必需的。然后你创建另一个DbSet项,例如DbSet<ItemView>
,它在数据库中与view而不是table相对应。在此视图的内部,您可以根据需要声明where语句。如果属性相同,您还可以为这两个类创建相同的祖先(例如Item
和ItemView
都继承自ItemBase
)。
我已经在MS SQL Server上完成了这项工作。
答案 1 :(得分:0)
我通常避免直接访问DbSet,并通过隐藏接口背后的上下文来强制实现这个想法。然后我只从界面访问存储库方法。如果您更喜欢客户端代码无法访问表集合(并希望将它们引导到某些已过滤的数据子集),则会在客户端代码中使用DbSets时隐藏智能感。 / p>
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();
}