我已经看过许多用EF实现存储库模式和UoW的教程,但我认为没有必要,因为DbSet和DbContext已经存在。 所以我决定在没有实现的情况下简化它,但是添加了诸如此类的服务。
public class HomeController : Controller
{
private IdbContext _dbContextUoW;
private IClientService _clientService;
public HomeController (IDbContext dbContextUoW,IClientService clientService){//IoC
this._dbContextUoW = dbContextUoW;
this._clientService = clientService;
}
public ActionResult Index()
{
List<Client> clients;
clients = List<Client>this._clientService(this._dbContextUoW).GetAll();
//this._dbContextUoW.SaveChanges()
return View();
}
}
public interface IClientService
{
List<Client> GetAll();
}
public class ClientService: IClientService
{
private IdbContextUoW _dbContextUoW;
public ClientService(IDbContext dbContextUoW){
this._dbContextUoW = dbContextUoW;
}
public List<Client> GetAll(){
return ...
}
}
此实施是否正确?我在正确的轨道上?
修改 我终于决定做以下事情,我不知道它是否是一个很好的解决方案,但对我来说似乎是,为每个服务创建一个通用的存储库。我的系列将具有基础CRUD操作(存储库)+逻辑操作(服务)
public abstract class GenericRepository<T> : IGenericRepository<T>
where T : EntityBase
{
protected IContext _entities;
protected readonly IDbSet<T> _dbset;
public GenericRepository(IContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual IEnumerable<T> GetAll()
{
...
}
public IEnumerable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
...
}
public virtual T Add(T entity)
{
...
}
public virtual T Delete(T entity)
{
...
}
public virtual void Edit(T entity)
{
...
}
public virtual void Save()
{
...
}
}
public class ClienteService : GenericRepository<Cliente>
{
IContext _context;
public ClienteService(IContext context)
:base(context)
{
_context = context;
}
public Cliente GetById(int Id)
{
return _dbset.FirstOrDefault(x => x.Id == Id);
}
}
答案 0 :(得分:1)
您需要每个请求/响应的dbcontext。
因此,在global.text中为CurrentContext创建一个属性。
public static YourDbContext CurrentContext
{
get { return (YourDbContext) HttpContext.Current.Items[Sessionkey]; }
private set { HttpContext.Current.Items[Sessionkey] = value; }
}
在application_beginrequest中,您希望实例化dbcontext并将其存储在HttpContext中
protected void Application_BeginRequest() { CurrentContext = new YourDbContext(); }
protected void Application_EndRequest()
{
if (CurrentContext != null)
CurrentContext.Dispose();
}
然后您可以连接您的IoC容器。这是城堡温莎
public class SessionInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container
.Register(Component.For<YourDbContext>().UsingFactoryMethod(() => MvcApplication.CurrentContext)
.LifeStyle
.PerWebRequest);
}
}
我还创建了一个Transaction属性来处理创建提交事务的过程。然后可以将此属性应用于控制器方法。
答案 1 :(得分:1)
我的第一个想法是您的域名服务看起来像一个存储库。 GetAll()
方法(从我的观点来看是有害的)不是您想要在服务层中找到的那种方法,通常有更复杂的方法来实现实际的域操作(其他范例中的业务操作) )。
如果您最终会使用与使用更方便的服务方法混淆的存储库相同的方法,那么您可能应该回到绝对抽象的方法。为了避免搞乱太多事情,您可以将扩展方法的额外方法实现为特定IDbSet<T>
(即IDbSet<Client>
,IDbSet<Product>
,{{1 }} ...)。也就是说,它们可以作为常规IDbSet<Whatever>
的一部分进行调用,并且您可以根据自己的责任将域名服务集中在他们真正想做的事情上。
我在前一段中建议您的示例扩展方法如下所示:
IDbSet<T>
关于不实现存储库和工作单元的完整抽象的事情,如果你正在处理,我会发现这个 ok 有一个小项目和一个有限的桶,你不需要长期思考,或者你不能希望你拥有实施单元测试套件的资源,你需要留在一些集成测试。
过度耦合特定工作单元或存储库实现的另一个缺点是实体框架提供的实现,微软可能会发展它产生可能完全破坏您的解决方案的重大变更。 显然,您还会发现其他众所周知的问题,例如无法使用NoSQL数据源并且难以实施单元测试。
总而言之,如果您要实施一个小型项目,那么采用您提出的方法应该没有麻烦......
答案 2 :(得分:-1)
存储库partern更好,因为您的服务将依赖于接口而不是实现。
如果您想将DbConnection与sql一起使用,您可以使用DbConnection实现。
如果你想拥有mongodb存储库,你可以使用它来实现。
使用存储库模式更好地分离职责的另一个好处。