在存储库模式加载子记录(Loading Subrecords in the Repository P

2019-06-27 16:48发布

使用LINQ to SQL作为一个基于库的解决方案的基础。 我的实现如下:

IRepository

FindAll
FindByID
Insert
Update
Delete

然后,我有一个用于查询结果作为这样的扩展方法:

WhereSomethingEqualsTrue() ...

我的问题如下:

我的用户资料库有N个角色。 难道我创建一个角色存储库来管理角色? 我担心,我会最终创造几十个库(1每桌几乎除了加入表),如果我走这条路。 每一个表共同库?

Answer 1:

如果您正在构建档案库具体到一个实体(表),使得每个实体都在你的IRepository接口,你上面列出的方法列表,然后你真正做的是一个执行活动记录模式。

绝对不应该有每桌一个存储库。 你需要确定你的域模型的集合,并且要对它们执行的操作。 用户和角色通常是紧密相关的,一般你的应用程序将与他们一前一后执行操作 - 这需要一个单一的存储库,围绕着用户,它的设置密切相关的实体。

我从您的文章,您已经猜测看到这个例子 。 这个例子的问题是,所有的仓库都在共享基础级别相同的CRUD功能,但他没有超越这一点,并实现任何域功能。 在例如所有的仓库看起来是一样的 - 但在现实中,真正的仓库不看起来都一样(尽管他们仍然应该接口),会有特定的域与每个人相关的操作。

您的仓库域操作应该更像:

userRepository.FindRolesByUserId(int userID)
userRepository.AddUserToRole(int userID)
userRepository.FindAllUsers()
userRepository.FindAllRoles()
userRepository.GetUserSettings(int userID)

等等...

这些都是具体的操作,你的应用程序需要对基础数据进行,和存储库应该提供。 你可以把它作为仓库代表一组,你会在域执行原子操作。 如果您选择通过一个通用的仓库来共享一些功能,并与扩展方法扩展特定信息库,这是一个办法,可以工作得很好,你的应用程序。

一个好的经验法则是,它应该是罕见您的应用程序需要实例多个存储库来完成的操作。 需要确实出现,但如果在你的应用程序的每个事件处理程序是杂耍6个仓库拿用户的输入,并正确实例化输入代表的实体,那么你可能有设计问题。



Answer 2:

每一个表共同库?

没有,但你仍然可以有多个存放区。 你应该建立一个围绕总的存储库。

此外,您可能能够抽象一些功能从所有仓库...和,因为你是使用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();
        }
    }


Answer 3:

对我来说,仓库格局即将把一个简单包装的数据访问方法。 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;
}

所以,这是一个有点散漫。 不知道如果我真的帮助任何,但我的建议是避免让与扩展方法太花哨,只是添加另一个层,以保持各运动部件的非常简单。 我的作品。



Answer 4:

如果我们写我们的代码库层越详细Womp表明,我们怎么把我们的服务层。 难道我们要重复相同的方法调用,这主要是由调用对应的库的方法,在我们的控制器或codebehinds使用? 这是假设你有一个服务层,你写你的验证,缓存,工作流程,认证/授权代码,对不对? 还是我大错特错?



文章来源: Loading Subrecords in the Repository Pattern