我正在设计我的ASP.NET MVC应用程序,我遇到了一些有趣的想法。
我见过的很多样本都描述并使用了Repository模式(IRepository
),所以这就是我在学习MVC时的方式。
现在我知道它正在做什么,我开始看看我目前的设计,并想知道这是否是最好的方式。
目前我有一个基本IUserRepository
,它定义了FindById()
,SaveChanges()
等方法。
目前,每当我想在数据库中加载/查询用户表时,我都会按照以下方式执行操作:
private IUserRepository Repository;
public UserController()
: this(new UserRepository())
{ }
[RequiresAuthentication]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Edit(string ReturnUrl, string FirstRun)
{
var user = Repository.FindById(User.Identity.Name);
var viewModel = Mapper.Map<User, UserEditViewModel>(user);
viewModel.FirstRun = FirstRun == "1" ? true : false;
return View("Edit", viewModel);
}
[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken(Salt = "SaltAndPepper")]
public ActionResult Edit(UserEditViewModel viewModel, string ReturnUrl)
{
//Map the ViewModel to the Model
var user = Repository.FindById(User.Identity.Name);
//Map changes to the user
Mapper.Map<UserEditViewModel, User>(viewModel, user);
//Save the DB changes
Repository.SaveChanges();
if (!string.IsNullOrEmpty(ReturnUrl))
return Redirect(ReturnUrl);
else
return RedirectToAction("Index", "User");
}
现在我还不完全了解MVC在用户创建链接时如何工作(不确定每个用户是否有1个控制器或每个应用程序有1个控制器),所以我不是肯定的最好的行动方案。
我发现了一个关于使用通用存储库接口IRepository<T>
here的一个很好的问题,并且在许多博客上似乎也有静态RepositoryFactory
的想法。基本上只保留一个存储库实例,它是通过这个工厂获得的
所以我的问题围绕着人们如何在应用程序中执行此操作,以及什么是良好的实践。
人们是否根据每个表格(IUserRepository
)设置了单独的存储库?
他们使用通用IRepository<T>
吗?
他们是否使用静态存储库工厂?
还是别的什么呢?
编辑: 我刚才意识到我也应该问:
每个控制器上有一个私有IRepository
是一个好方法吗?或者我应该每次想要使用它时实例化一个新的IRepository
?
BOUNTY编辑: 我开始获得更多的观点(不是蒂姆没有帮助)。
我更想知道人们在他们的MVC应用程序中做了什么,或者他们认为什么是个好主意。
答案 0 :(得分:24)
答案 1 :(得分:3)
人们是否有基于每个表(IUserRepository)的个人存储库? 我倾向于为每个聚合而不是每个表都有一个存储库。
他们是否使用通用IRepository? 如果可能的话,是的
他们是否使用静态存储库工厂? 我更喜欢通过IOC容器注入Repository实例
答案 2 :(得分:1)
以下是我如何使用它。我正在使用IRepository进行我所有存储库共有的所有操作。
public interface IRepository<T> where T : PersistentObject
{
T GetById(object id);
T[] GetAll();
void Save(T entity);
}
我还为每个aggregate使用了一个专用的ITRepository,用于与此存储库不同的操作。例如,对于用户,我将使用IUserRepository添加与UserRepository不同的方法:
public interface IUserRepository : IRepository<User>
{
User GetByUserName(string username);
}
实现将如下所示:
public class UserRepository : RepositoryBase<User>, IUserRepository
{
public User GetByUserName(string username)
{
ISession session = GetSession();
IQuery query = session.CreateQuery("from User u where u.Username = :username");
query.SetString("username", username);
var matchingUser = query.UniqueResult<User>();
return matchingUser;
}
}
public class RepositoryBase<T> : IRepository<T> where T : PersistentObject
{
public virtual T GetById(object id)
{
ISession session = GetSession();
return session.Get<T>(id);
}
public virtual T[] GetAll()
{
ISession session = GetSession();
ICriteria criteria = session.CreateCriteria(typeof (T));
return criteria.List<T>().ToArray();
}
protected ISession GetSession()
{
return new SessionBuilder().GetSession();
}
public virtual void Save(T entity)
{
GetSession().SaveOrUpdate(entity);
}
}
在UserController中将显示为:
public class UserController : ConventionController
{
private readonly IUserRepository _repository;
private readonly ISecurityContext _securityContext;
private readonly IUserSession _userSession;
public UserController(IUserRepository repository, ISecurityContext securityContext, IUserSession userSession)
{
_repository = repository;
_securityContext = securityContext;
_userSession = userSession;
}
}
使用自定义控制器工厂使用依赖注入模式实例化存储库。我正在使用StructureMap作为我的依赖注入层。
数据库层是NHibernate。 ISession是此会话中数据库的网关。
我建议您查看CodeCampServer结构,您可以从中学到很多东西。
您可以从中学到的另一个项目是Who Can Help Me。我还没有深入挖掘它。
答案 3 :(得分:0)
人们是否根据每个表(IUserRepository)拥有单独的存储库?
是的,这是更好的选择,有两个原因:
他们是否使用通用IRepository?
是的,完全,受DDD实体/价值计划启发我创建了IRepositoryEntity / IRepositoryValue和其他东西的通用IRepository。
他们是否使用静态存储库工厂?
是和否:我使用通过静态类调用的 IOC容器。 嗯......我们可以说它是一种工厂。
注意:我自己设计了这个架构,我的一位同事发现它非常棒,我们目前正在这个模型上创建我们的整个公司框架(是的,它是一家年轻的公司)。这绝对是值得尝试的事情,即使我觉得那些框架将由主要演员发布。
答案 4 :(得分:0)
您可以找到一个出色的 Generic Repopsitory 库,以便在Codeplex上使用它作为WebForms asp:ObjectDataSource:MultiTierLinqToSql
我的每个控制器都有他们需要支持的操作的私有存储库。