修改
我应该将服务层和存储库层放入一个项目中,以便Web项目能够引用DbContext对象吗?现在我的web(控制器)无法引用dbcontext对象。什么是正确的方法?
// service and repository are together
(View <- Controller) -> (Service -> Repository -> EF DbContext) -> (DB)
// separate service and repository layer
(View <- Controller) -> (Service) -> (Repository -> EF DbContext) -> (DB)
以下是原始问题
我知道SO是一个很好的社区,可以发布关于mvc设计模式的问题。请给我你的建议,我将非常感谢你的帮助。谢谢!
我们正在计划一个新项目,我们的首要任务是开发一个可扩展且松散耦合的应用程序。
我是软件开发的新手;我在MVC Music Store Tutorial上做了一些阅读,然后是一本名为Pro ASP.NET MVC 3 Framework by Steven Sanderson (Apress)的书,从书中我了解了DDD(域驱动设计)和其他一些概念,如存储库和依赖注入。我按照这本书建立了SportsStore网站,并对DI有了一些基本的了解。但我个人认为这个例子没有将业务逻辑层分开,所以我对此进行了研究,我发现了一种称为服务层模式的模式,根据我的理解,它将业务逻辑层分开。基于此,我为我的新项目(下面的示例项目)提出了一个结构。
我是否需要实施 IDisposable 界面?如果是的话,在哪里和为什么? 这种结构对于一个规模较大的项目是否可行?
示例数据库设计:产品(一)----(很多)ProductCategoryRs(很多)----(一)类别
该解决方案包含3个项目:存储库,服务,Web
存储库:
定义IRepository接口,基本CRUD操作
这些签名是否足够?我应该添加 TEntity GetById(对象ID); 吗?
public interface IRepository<TEntity>
{
IQueryable<TEntity> All { get; }
void Create(TEntity item);
void Update(TEntity item);
void Delete(TEntity item);
void SaveChanges();
}
实施通用存储库类
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
STOREEntities context;
public Repository()
{
context = new STOREEntities();
}
public IQueryable<TEntity> All
{
get
{
return context.Set<TEntity>();
}
}
public void Create(TEntity item)
{
context.Set<TEntity>().Add(item);
}
public void Update(TEntity item)
{
context.Entry<TEntity>(item).State = System.Data.EntityState.Modified;
}
public void Delete(TEntity item)
{
context.Set<TEntity>().Remove(item);
}
public void SaveChanges()
{
context.SaveChanges();
}
}
服务: 定义IProductService接口,在此处扩展业务逻辑。
public interface IProductService
{
IEnumerable<Product> Products { get; }
IEnumerable<Product> Get(Expression<Func<Product, Boolean>> filter);
Product GetByProductId(int productId);
void AddProduct(Product product);
void EditProduct(Product product);
void RemoveProduct(Product product);
void SaveChanges();
}
实施产品服务
public class ProductService : IProductService
{
IRepository<Product> repository; //Inject
public ProductService(IRepository<Product> repo)
{
repository = repo;
}
public IEnumerable<Product> Products
{
get { return repository.All; }
}
public IEnumerable<Product> Get(Expression<Func<Product, bool>> filter)
{
return repository.All.Where(filter);
}
public Product GetByProductId(int productId)
{
return repository.All.SingleOrDefault(p => p.ProductID == productId);
}
public void AddProduct(Product product)
{
repository.Create(product);
}
public void EditProduct(Product product)
{
repository.Update(product);
}
public void RemoveProduct(Product product)
{
repository.Delete(product);
}
public void SaveChanges()
{
repository.SaveChanges();
}
}
Web项目,从服务中检索数据并转换为viewmodel并显示。 ProductController代码
public class ProductController : Controller
{
IProductService productService; //inject
public ProductController(IProductService service)
{
productService = service;
}
public ActionResult Index()
{
var products = productService.Products; //retrieve from service layer
return View(products);
}
}
答案 0 :(得分:2)
我相信你确实将TEntity GetById(int id)
添加到IRepository<TEntity>
通用界面。
为什么呢?因为如果不这样做,并且如果要在业务层上获取单个记录,则只有两个选项(在存储库,数据访问层):
IQueryable<TEntity>
这样的惰性集合,是的,允许您从数据库中获取单个记录,但可能会导致大量nasty side-effects。第一种选择显然是错误的。第二个是有争议的,但(除非你的项目让你作为一个开发人员,你真的真的知道你在做什么),它可能是漏洞和不安全的。因此,如果您确实需要一条记录(有时您肯定会这样做),请公开一个完全符合该记录的方法。
话虽如此,您也应该不公开IQueryable<TEntity> All { get; }
,原因完全相同。请改用IEnumerable<TEntity> All { get; }
,并通过调用context.Set<TEntity>().ToList()
使您的具体通用存储库类返回一个真实的集合。
修改强>
关于IDisposable:
实现我能想到的IDisposable接口只有两个(相关)原因:
在您的情况下,您可能应该在您的存储库实现上使用它。请查看this SO question以获取更多信息。