什么属于存储库,什么不属于存储库?

发布于 2024-08-01 21:12:32 字数 530 浏览 2 评论 0原文

在实现存储库模式的 ASP.NET MVC 应用程序中,我很好奇如果非数据相关方法仍然属于给定存储库的一般焦点,是否适合将它们放置在存储库中。 例如,假设一个 ProductsRepository 具有添加和删除 ProductImages 的方法,这些 ProductImages 在数据库和本地文件存储中也有部分表示。 如果需要删除 ProductImage,我们需要使用存储库方法从数据库中删除一行,并且还需要从存储介质中删除与该图像关联的文件。 IO 操作是否属于存储库,或者是否有更合适的位置?

在类似我刚才描述的情况下,我一直在做的一件事是在我的存储库中提供静态方法,这些方法通过使用存储在数据库中的文件名和预定义的目录模式以编程方式生成它,为我提供给定 ProductImage 的路径。 这是否超出了存储库的预期用途?


编辑

如果这样的操作不属于存储库,那么在 MVC 模式中类似的操作应该放在哪里? 在我看来,在控制器和存储库之间设置另一层可能是有意义的,该层根据需要调用存储库,并且可以从控制器静态调用。

In an ASP.NET MVC application implementing the repository pattern I am curious if it is appropriate to place non-data related methods in the repository if they still pertain to the general focus of a given repository. For example, suppose a ProductsRepository that has methods for adding and deleting ProductImages which have a partial representation in the database and in the local file store as well. If a ProductImage needs to be deleted we need to delete a row from the database with a repository method and we also need to delete the files associated with that image from the storage medium. Do the IO operations belong in the repository, or is there a more appropriate location?

One thing I have been doing in a situation like the one I just described is providing static methods in my repository which give me the path to a given ProductImage by using the filename stored in the database and a pre-defined directory pattern to programatically generate it. Is this outside the intended use of a repository?


Edit

If such an operation does not belong in the repository, where should something like that go in an MVC pattern? It seems to me that it might make sense to have another layer between the Controller and the Repository that calls the Repository as needed and can be invoked statically from the Controller.

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

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

发布评论

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

评论(3

稚气少女 2024-08-08 21:12:32

存储库的作用是将应用程序与它所使用的数据的存储方式和位置隔离开来。 在此基础上,存储库绝对是在此上下文中处理数据库和基于文件的活动的正确位置。

The repository is there to isolate the application from the concerns of how and where the data it's consuming is stored. On that basis, the repository is absolutely the right place to handle both the database and the file-based activities in this context.

撕心裂肺的伤痛 2024-08-08 21:12:32

我最近设计了一个新的存储库,并为同样的问题而苦苦挣扎。 我最终将我的附加方法包含在存储库中。

现在回想起来,我觉得更好的解决方案是让我的存储库更加集中,并将我的附加方法放入与我的存储库紧密集成的服务中。

对于上面的示例,您可以在 ProductsService 中使用“DeleteProductImage”方法,该方法将调用 ProductsRepository.DeleteImage & 然后还要处理从存储介质中删除图像。

这可以使您的存储库保持干净并仅专注于“DeleteImage”逻辑,同时仍然为您提供需要调用的单个方法(“DeleteProductImage”),该方法负责调用存储库来删除图像,同时还处理与存储介质的交互以及删除图像时可能需要发生的任何其他与您的存储库不直接相关的事情。

I recently designed a new repository and struggled with this same question. I ended up including my additional methods in the repository.

Looking back at it now though, I feel that a better solution would have been to keep my repository more focused, and to have put my additional methods into a Service that integrated closely with my repository.

For your example above, you could then have a "DeleteProductImage" method in ProductsService that would call ProductsRepository.DeleteImage & then also handle deleting the images from the storage medium.

This keeps your Repository clean and focused on just the "DeleteImage" logic, while still giving you a single method you need to call ("DeleteProductImage") which takes care of calling the repository to delete the image while also handling interacting with the storage medium and any other things that may need to happen when an Image is deleted that aren't directly related to your repository.

情释 2024-08-08 21:12:32

我认为对存储库模式更大的担忧是您违反了单一责任原则。 您的类应该承担一项职责,例如操作数据库中的数据。 您应该有一个不同的类来处理文件 IO,并且您可以将函数分组到一个类中的上一层。

类的更改应该只有一个原因,而处理文件 IO 和数据库调用的存储库类将有两个原因。 文件系统布局的更改或数据库的更改。

编辑

为了解决您的编辑问题,以下是我在 MVC 场景中实现这一点的方法(这也假设您正在使用某种依赖注入来使生活更轻松)。

// Controller class
public class ProductsController
{
    private IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService
    }

    public void RemoveImage(int productId, int imageId)
    {
        _productService.RemoveImage(productId, imageId)
    }
}

public class ProductService: IProductService
{
    private IProductRepository _productRepository;
    private IProductImageManager _imageManager;

    public ProductService(IProductRepository productRepository, IProductImageManager imageManager)
    {
      _productRepository = productRepository;
      _imageManager = imageManager;
    }

    public void RemoveImage(int productId, int imageId)
    {
        // assume some details about locating the image are in the data store
        var details = _productRepository.GetProductImageDetails(productId, imageId);
        // TODO: error handling, when not found?
        _imageManager.DeleteImage(details.location);
        _productRepository.DeleteImage(productId, imageId)
    }
}

然后,您可以根据任何有意义的接口来实现 IProductImageManager 和 IProductRepository,并根据您的特定需求进行具体实现。

I think the bigger concern over the repository pattern is the fact that you are violating single responsibility principle. Your class should have one responsibility, such as manipulating data in the database. You should have a different class deal with the File IO, and you can group the functions in a class one layer up.

There should only be one reason for a class to change, and a repository class that handles file IO and db calls will have two. A change to the file system layout, or a change to the database.

Edit

To address your edit question, here is how I would implement this in an MVC scenario (this is also assuming you are using some kind of dependency injection to make life easier).

// Controller class
public class ProductsController
{
    private IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService
    }

    public void RemoveImage(int productId, int imageId)
    {
        _productService.RemoveImage(productId, imageId)
    }
}

public class ProductService: IProductService
{
    private IProductRepository _productRepository;
    private IProductImageManager _imageManager;

    public ProductService(IProductRepository productRepository, IProductImageManager imageManager)
    {
      _productRepository = productRepository;
      _imageManager = imageManager;
    }

    public void RemoveImage(int productId, int imageId)
    {
        // assume some details about locating the image are in the data store
        var details = _productRepository.GetProductImageDetails(productId, imageId);
        // TODO: error handling, when not found?
        _imageManager.DeleteImage(details.location);
        _productRepository.DeleteImage(productId, imageId)
    }
}

Then you implement the IProductImageManager and the IProductRepository based on whatever interface makes sense with concrete implementations for your specific needs.

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