Although you already accepted an (altogether acceptable) answer that addresses lifetime issues, I think the most important aspect has only be skimmed in Chris's answer. The most important reason why (IMHO) it should be option 1 is composability. (But an important assumption is that in option 1 the repository receives a context in its constructor, so this context can be shared by multiple repositories in one use case).
Suppose you want to join two entities in one query:
from u in repo1.GetUsers()
join r in repo2.GetRoles() on u.UserId equals r.UserId
where u.UserId = ...
With option 2 this would execute separate queries for users and roles, because two DbSet
s from different contexts can only be combined in memory. With option 1 (and some modifications) this will fire one composed query with a SQL join.
What you'll need do do additionally, is return IQueryable
in stead of List
, i.e. just return context.Users
.
Also, with option 2, if you make changes to entities from different repositories it is much more elaborate to commit them in one transaction. (You need SaveChanges()
calls in each context, wrapped in a TransactionScope
).
A bit off-topic, but too relevant to omit is the fact that the modified option 1 would probably leave you with a very, very thin middleman between DbSet
s and your application code. You may decide that this repository layer doesn't add anything useful and ditch it altogether.