2

我正在使用实体框架和 SQL Server 2008 作为数据存储的 ASP.Net MVC3 网站。此外,我正在使用存储库模式将所有数据访问代码集中在一个区域中。

在我的应用程序中,我有很多用户,每个用户都可以有很多项目。用户应该只能访问他们自己的项目。目前我有这个代码:

    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; }
}

或者

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在写这个问题的时候,意识到最后一个版本可以正常工作——需要尝试一下。仍然希望听到其他代码优化选项并使其更加干燥。

提前致谢!!

4

1 回答 1

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();
}

这样,从方法名上,就很清楚自己在做什么了。存储库不负责包含您的特定逻辑。它仅用于处理您的数据访问。

于 2012-05-27T00:45:55.010 回答