2

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

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

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

4

1 回答 1

1

很难给出明确的答案,但您可以通过实现更高阶的函数使其更具可扩展性,如下所示:

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 而不是 CustomerID 获取 File 对象,则:

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”表达式嫁接到最终传递给数据库的内容上。当然,任何只关心使用基本存储库的东西,仍然可以这样做。

于 2012-11-18T10:23:47.720 回答