实体框架为所有查询添加where子句

时间:2012-11-18 00:02:14

标签: asp.net-mvc entity-framework ef-code-first repository

我正在使用Entity framework 5并使用存储库模式。假设我有这些实体客户,文件,图像,任务,发票,用户。

每个实体(除客户外)都有客户的外键。当用户登录时,我将customerid存储在会话中(aps.net mvc)。我想要的是所有实体上的CRUD仅限于用户登录的客户。例如,我不能删除属于客户1的任务,由来自客户2的用户删除。

为每个存储库方法添加customerid参数是实现此目的的最佳方法还是有更好/更聪明的方法?

1 个答案:

答案 0 :(得分:1)

Tricky给出一个明确的答案,但你可以通过实现更高的顺序函数使它更具可扩展性,如下所示:

public interface IRepository<T>
{
    public T GetBy(Expression<Func<T, bool>> query)
}


public class FileRepository : IRepository<File>
{
    public File GetBy(Expression<Func<T, bool>> query)
    {
        using(var context = new FilesContext())
        {
            return context.Files.Where(query).FirstOrDefault();
        }
    }

}

public class SomeController
{
    private IRepository<File> _repo;

    public SomeController(IRepository<File> repo)
    {
        _repo = repo;
    }

   public ActionResult Index()
   {
       var model = _repo.GetBy(f => f.CustomerId == Session.Whatever.CustomerId);

       return View(model);
   }

}

这样,您可以在需要时更改搜索查询,而不是将自己绑定到使用硬编码的客户ID属性。例如,如果您想通过FileID获取File对象,而不是CustomerID,那么:

var model = _repo.GetBy(f => f.FileId == someId);

这是代码中唯一需要更改的部分。

关于C#中的高阶函数和函数式编程的一些非常好的信息:http://www.codeproject.com/Articles/375166/Functional-programming-in-Csharp

修改

您可以使用装饰器样式模式将“在使用DB时始终使用客户ID”隔离到其自己的存储库中,从而:(大量免责声明 - 我没有对此进行了测试,但这些方面的内容应该有效)

public class SpecialFileRepo : IRepository<File>
{
    private readonly IRepository<File> _baseRepo;

    public SpecialFileRepo(IRepository<File> baseRepo)
    {
        _baseRepo = baseRepo;
    }

    public SpecialFileRepo() : this(new FileRepository())
    {

    }
    public File GetBy(Expression<Func<File, bool>> query)
    {
        var parameters = query.Parameters;
        var newParam = Expression.Parameter(typeof (File), "f");

        var additionalQuery = Expression.AndAlso(query.Body,
                                                 Expression.Equal(
                                                     Expression.PropertyOrField(newParam, "CustomerId"),
                                                     Expression.Constant(HttpContext.Current.Session["customerId"])));

        var newQuery = query.Update(additionalQuery, parameters);


        return _baseRepo.GetBy(newQuery);
    }
}

然后,任何与存储库交谈的内容,就其而言,它只是一个基本存储库,但是这个类位于中间并始终将“customerid = sessionwhatever”表达式移植到最终传递给数据库的内容上。当然,任何只关心使用基础存储库的东西仍然可以这样做。