我正在使用Entity Framework和SQL Server 2008作为数据存储的ASP.Net MVC3网站。此外,我正在使用Repository模式将所有数据访问代码集中在一个区域中。
在我的应用程序中,我有很多用户,每个用户都可以有很多项目。用户应该只能访问自己的项目。 目前我有这段代码:
public IQueryable<Project> All
{
get {
return context.Projects
.Where(p => p.Owner.ID == Util.GetCurrentUserID())
.Select(p=>p);
}
}
public Project Find(System.Guid id)
{
return context.Projects
.Where(p => p.Owner.ID == Util.GetCurrentUserID())
.FirstOrDefault();
}
如果您发现.Where(p => p.Owner.ID == Util.GetCurrentUserID())
重复。而且我还有其他一些地方,这些确切的条件都散落在其中。
DbContext中是否有一种方法可以将此条件自动附加到任何进入Projects表的查询中?
类似的东西:
public class MyContext : DbContext
{
public DbSet<Project> Projects
.Where(p => p.Owner.ID == Util.GetCurrentUserID()) { get; set; }
}
OR
public class MyContext : DbContext
{
public DbSet<Project> Projects { get {
// Insert a cast from IQuerieable to DBSet below
return Projects
.Where(p => p.Owner.ID == Util.GetCurrentUserID())
.Select(p => p);
}
set; }
}
UPD 在撰写问题时,意识到最后一个版本可以正常工作 - 需要尝试一下。仍然希望听到代码优化的其他选项,并使其更加干燥。
提前致谢!!
答案 0 :(得分:4)
您始终可以编写名为“WhereProject”的扩展方法。然后在将条件附加到谓词后,在扩展方法中调用标准的“Where”方法。
public static IEnumerable<TSource> WhereProject<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) where TSource: Project
{
return source.Where(p=> p.Owner.ID == Util.GetCurrentUserID() && predicate);
}
如果需要,可以跳过谓词,或者在默认值的参数列表中将其设置为null,如果不想使用谓词,则可以相应地执行操作。
这可能是你想要的,很简单:
public static IEnumerable<TSource> WhereProject<TSource>(this IEnumerable<TSource> source) where TSource: Project
{
return source.Where(p=> p.Owner.ID == Util.GetCurrentUserID());
}
修改强> 这些解决方案对我来说听起来不对。我认为您希望将行数据保持在一个更高的级别,在我的情况下,它将是服务层。在服务类中考虑一个方法,如下所示:
public List<Project> GetUserProjects(User user)
{
return repo.All().Where(p => p.Owner.ID == Util.GetCurrentUserID()).ToList();
}
这样,从方法名称来看,你在做什么就很清楚了。包含特定逻辑的存储库不是责任。它只能处理您的数据访问。