存储库模式中的共享存储库

发布于 2024-10-10 17:41:26 字数 701 浏览 3 评论 0原文

存储库依赖?假设我有一个如下所示的域:

public class User
{
    public int UserId { get; set; }
    public Lazy<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public User Poster { get; set; }
}

具有我的帖子的用户。

如何设置我的存储库,以便对于每个用户,它返回一个Post列表,对于每个post,我得到海报

我有 2 个存储库:

public class UserRepository : IUserRepository
{
    public IQueryable<User> GetUsers();
}

public class PostRepository : IPostRepository
{
    public IQueryable<Post> GetPosts();
}

我尝试从 1 个存储库调用另一个存储库,但由于存在循环依赖,最终导致崩溃。

我正在将存储库模式的 POCO 方法与实体框架结合使用。

Repository dependency? Lets say I have a domain that looks like the following:

public class User
{
    public int UserId { get; set; }
    public Lazy<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public User Poster { get; set; }
}

A user with my posts.

How do I set up my repository so that for every user, it returns a list of Post and for every post, I get the Poster?

I have 2 repositories:

public class UserRepository : IUserRepository
{
    public IQueryable<User> GetUsers();
}

public class PostRepository : IPostRepository
{
    public IQueryable<Post> GetPosts();
}

I tried calling from 1 repository to the other, but it ends up in a crash because there is a circular dependency.

I'm using the POCO method of the repository pattern with entity framework.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

还不是爱你 2024-10-17 17:41:26

我有 2 个存储库:

公共类 UserRepository : IUserRepository
{
    公共 IQueryable<用户>;获取用户();
}

公共类 PostRepository :IPostRepository
{
    公共 IQueryable获取帖子();
}

这可能会成为问题。

您可能不想简单地GetUsers。正如您所说,您希望子实体加载聚合或顶级实体。

将会发生的情况是,根据使用环境(您的直接目的是什么),您将需要该用户的变化。您可能最终会得到诸如 GetUsersGetUsersWithPostsGetUsersForImportantReportGetUsersForAttendingAnIceCreamSocial 等方法。 ., 令人作呕。

缺少的是角色的概念。

您检索用户的角色是什么?此处明确建模。

从聚合的基本接口开始。基本属性可以在此处

public interface IUser {
  public Guid UserId { get; set; }
  public string UserName { get; set; }
  public IEnumerable<Posts> { get; set; }
}

添加接口以支持您将在其中使用用户的角色。

public interface IAddPostsToUser : IUser {
  public void AddPost(Post post);
}

您的存储库可以这样定义:

public interface IUserRepository {
  User Get<TRole>(Guid userId) where TRole : IUser;
}

现在,使用该角色来定义获取策略;

public interface IFetchingStrategy<TRole> {
  TRole Fetch(Guid id, IRepository<TRole> role)
}

您的存储库将通过注入或服务定位来获取获取策略并调用获取。您可以传入存储库来为 FetchingStrategy 提供查询机制,或者让 FetchingStrategy 注入或定位它需要查询的服务。

当然,具体如何查询将取决于您的 ORM。

但这种建模方式将有助于避免在不同场景下加载实体图时出现的许多问题。

I have 2 repositories:

public class UserRepository : IUserRepository
{
    public IQueryable<User> GetUsers();
}

public class PostRepository : IPostRepository
{
    public IQueryable<Post> GetPosts();
}

This is likely to become problematic.

You likely don't want to simply GetUsers. As you say, you want child entities loaded with the aggregate, or top-level, entity.

What will occur is that depending on the context of use - what your immediate purpose is - you will want variations on that User. You'll likely end up with methods like GetUsers, 'GetUsersWithPosts, GetUsersForImportantReport, GetUsersForAttendingAnIceCreamSocial, etc., etc., ad nauseam.

What's missing is the concept of a role.

What role are you retrieving the User for? Model that explicitly here.

Start with a base interface for your aggregate. Basic properties can go here

public interface IUser {
  public Guid UserId { get; set; }
  public string UserName { get; set; }
  public IEnumerable<Posts> { get; set; }
}

Add interfaces to support the roles in which you will use the user.

public interface IAddPostsToUser : IUser {
  public void AddPost(Post post);
}

And your repository can be defined as such:

public interface IUserRepository {
  User Get<TRole>(Guid userId) where TRole : IUser;
}

Now, use that role to define a fetching strategy;

public interface IFetchingStrategy<TRole> {
  TRole Fetch(Guid id, IRepository<TRole> role)
}

Your repository would get the fetching strategies through injection or service location and call fetch. You can pass the repository in to provide the mechanism for the FetchingStrategy to query or have the FetchingStrategy inject or locate what services it needs to query.

Of course, exactly how you query will depend on your ORM.

But this way of modeling will help avoid many problems with loading entity graphs in different scenarios.

疧_╮線 2024-10-17 17:41:26

恕我直言,这属于服务层,而不是存储库层。存储库只是包装数据库。

public IQueryable<UserData> GetUsersWithPosts()
{
    return from u in UserRepository.GetUsers()
           select new UserData 
           {
               Id = u.Id,
               Name = u.Name
               Posts = from p in u.Posts
                       select new PostData
                       {
                           Id = u.Id,
                           Title = p.Title
                       }
           };

...根据需要添加安全问题、聚合等。

IMHO, this belongs in the service layer, not the repository layer. Repository just wraps the DB.

public IQueryable<UserData> GetUsersWithPosts()
{
    return from u in UserRepository.GetUsers()
           select new UserData 
           {
               Id = u.Id,
               Name = u.Name
               Posts = from p in u.Posts
                       select new PostData
                       {
                           Id = u.Id,
                           Title = p.Title
                       }
           };

...add security concerns, aggregation, etc, as needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文