2

Entity Framework 5を使用しており、リポジトリパターンを使用しています。これらのエンティティCustomer、Files、Images、Tasks、Invoice、Userを取得したとします。

各エンティティ(顧客を除く)には、顧客の外部キーがあります。ユーザーがログインすると、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プロパティを使用するのではなく、必要に応じて検索クエリを変更できます。たとえば、CustomerIDではなくFileIDで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 に答える