使用LINQ to SQL作为一个基于库的解决方案的基础。 我的实现如下:
IRepository
FindAll
FindByID
Insert
Update
Delete
然后,我有一个用于查询结果作为这样的扩展方法:
WhereSomethingEqualsTrue() ...
我的问题如下:
我的用户资料库有N个角色。 难道我创建一个角色存储库来管理角色? 我担心,我会最终创造几十个库(1每桌几乎除了加入表),如果我走这条路。 每一个表共同库?
使用LINQ to SQL作为一个基于库的解决方案的基础。 我的实现如下:
IRepository
FindAll
FindByID
Insert
Update
Delete
然后,我有一个用于查询结果作为这样的扩展方法:
WhereSomethingEqualsTrue() ...
我的问题如下:
我的用户资料库有N个角色。 难道我创建一个角色存储库来管理角色? 我担心,我会最终创造几十个库(1每桌几乎除了加入表),如果我走这条路。 每一个表共同库?
如果您正在构建档案库具体到一个实体(表),使得每个实体都在你的IRepository接口,你上面列出的方法列表,然后你真正做的是一个执行活动记录模式。
你绝对不应该有每桌一个存储库。 你需要确定你的域模型的集合,并且要对它们执行的操作。 用户和角色通常是紧密相关的,一般你的应用程序将与他们一前一后执行操作 - 这需要一个单一的存储库,围绕着用户,它的设置密切相关的实体。
我从您的文章,您已经猜测看到这个例子 。 这个例子的问题是,所有的仓库都在共享基础级别相同的CRUD功能,但他没有超越这一点,并实现任何域功能。 在例如所有的仓库看起来是一样的 - 但在现实中,真正的仓库不看起来都一样(尽管他们仍然应该接口),会有特定的域与每个人相关的操作。
您的仓库域操作应该更像:
userRepository.FindRolesByUserId(int userID)
userRepository.AddUserToRole(int userID)
userRepository.FindAllUsers()
userRepository.FindAllRoles()
userRepository.GetUserSettings(int userID)
等等...
这些都是具体的操作,你的应用程序需要对基础数据进行,和存储库应该提供。 你可以把它作为仓库代表一组,你会在域执行原子操作。 如果您选择通过一个通用的仓库来共享一些功能,并与扩展方法扩展特定信息库,这是一个办法,可以工作得很好,你的应用程序。
一个好的经验法则是,它应该是罕见您的应用程序需要实例多个存储库来完成的操作。 需要确实出现,但如果在你的应用程序的每个事件处理程序是杂耍6个仓库拿用户的输入,并正确实例化输入代表的实体,那么你可能有设计问题。
每一个表共同库?
没有,但你仍然可以有多个存放区。 你应该建立一个围绕总的存储库。
此外,您可能能够抽象一些功能从所有仓库...和,因为你是使用LINQ到SQL,你也许可以......
你可以实现一个基础库,其在通用的方式实现这一切的常见功能。
下面的例子只是为了证明这一点。 它可能需要大量的改进......
interface IRepository<T> : IDisposable where T : class
{
IEnumerable<T> FindAll(Func<T, bool> predicate);
T FindByID(Func<T, bool> predicate);
void Insert(T e);
void Update(T e);
void Delete(T e);
}
class MyRepository<T> : IRepository<T> where T : class
{
public DataContext Context { get; set; }
public MyRepository(DataContext context)
{
Context = Context;
}
public IEnumerable<T> FindAll(Func<T,bool> predicate)
{
return Context.GetTable<T>().Where(predicate);
}
public T FindByID(Func<T,bool> predicate)
{
return Context.GetTable<T>().SingleOrDefault(predicate);
}
public void Insert(T e)
{
Context.GetTable<T>().InsertOnSubmit(e);
}
public void Update(T e)
{
throw new NotImplementedException();
}
public void Delete(T e)
{
Context.GetTable<T>().DeleteOnSubmit(e);
}
public void Dispose()
{
Context.Dispose();
}
}
对我来说,仓库格局即将把一个简单包装的数据访问方法。 LINQ到你的情况SQL,但在其他NHibernate的,手卷。 什么我发现自己做的事情是建立一个资料库,每表,是非常简单的(像布鲁诺列出你已经有了)。 这是负责寻找的东西,做CRUD操作。
但后来我有一个与总根源涉及多个服务水平,约翰内斯提到。 我会与像GetExistingUser(INT ID)的方法的UserService。 这将在内部调用UserRepository.GetById()方法来获取用户。 如果你的业务流程需要通过GetExistingUser返回用户类()到几乎总是需要User.IsInRoles()来填充属性,那么只需将UserService取决于两个UserRepository 和 RoleRepository。 在伪代码可能是这个样子:
public class UserService
{
public UserService(IUserRepository userRep, IRoleRepository roleRep) {...}
public User GetById(int id)
{
User user = _userService.GetById(id);
user.Roles = _roleService.FindByUser(id);
return user;
}
该userRep和roleRep将与您的LINQ被构造为SQL位是这样的:
public class UserRep : IUserRepository
{
public UserRep(string connectionStringName)
{
// user the conn when building your datacontext
}
public User GetById(int id)
{
var context = new DataContext(_conString);
// obviously typing this freeform but you get the idea...
var user = // linq stuff
return user;
}
public IQueryable<User> FindAll()
{
var context = // ... same pattern, delayed execution
}
}
我个人做仓库类在内部范围的,并有UserService和其他XXXXXService类公共所以保持你的服务API的消费者诚实。 所以,我再次看到版本库的联系更加紧密地说着到数据存储的行为,但你的服务层被更紧密地对准你的业务流程的需求。
我经常发现自己得太多真中的LINQ到对象的灵活性和所有的东西,并使用IQuerable 等人 ,而不是那吐出什么,我真正需要的只是建立服务方法。 用户LINQ在适当情况下,但不要试图让程序存储库做的一切。
public IList<User> ActiveUsersInRole(Role role)
{
var users = _userRep.FindAll(); // IQueryable<User>() - delayed execution;
var activeUsersInRole = from users u where u.IsActive = true && u.Role.Contains(role);
// I can't remember any linq and i'm type pseudocode, but
// again the point is that the service is presenting a simple
// interface and delegating responsibility to
// the repository with it's simple methods.
return activeUsersInRole;
}
所以,这是一个有点散漫。 不知道如果我真的帮助任何,但我的建议是避免让与扩展方法太花哨,只是添加另一个层,以保持各运动部件的非常简单。 我的作品。
如果我们写我们的代码库层越详细Womp表明,我们怎么把我们的服务层。 难道我们要重复相同的方法调用,这主要是由调用对应的库的方法,在我们的控制器或codebehinds使用? 这是假设你有一个服务层,你写你的验证,缓存,工作流程,认证/授权代码,对不对? 还是我大错特错?