asp.net-mvc - 使用 LINQ2SQL 限制对特定字段的更改时的最佳实践

标签 asp.net-mvc linq-to-sql design-patterns repository

我正在阅读 Steven Sanderson 的书 Pro ASP.NET MVC Framework,他建议使用存储库模式:

public interface IProductsRepository
{
    IQueryable<Product> Products { get; }
    void SaveProduct(Product product);
}

他直接从他的 Controller 访问产品存储库,但由于我将同时拥有一个网页和 Web 服务,我想添加一个将由 Controller 和 Web 服务调用的“服务层”:
public class ProductService
{
    private IProductsRepository productsRepsitory;

    public ProductService(IProductsRepository productsRepository)
    {
        this.productsRepsitory = productsRepository;
    }

    public Product GetProductById(int id)
    {
        return (from p in productsRepsitory.Products
                where p.ProductID == id
                select p).First();
    }

    // more methods
}

这看起来一切都很好,但我的问题是我不能使用他的 SaveProduct(Product product) 因为:

1) 我只想允许在 Product 表中更改某些字段

2)我想保留对 Product 表的每个字段所做的每次更改的审核日志,因此我必须为每个允许更新的字段提供方法。

我最初的计划是在 ProductService 中有一个这样的方法:
public void ChangeProductName(Product product, string newProductName);

然后调用 IProductsRepository.SaveProduct(Product)

但是我看到了一些问题:

1)这样传入Product对象不是很“OO”吗?但是,我看不出这段代码如何进入 Product 类,因为它应该只是一个哑数据对象。我可以看到向部分类添加验证,但不是这个。

2)在我坚持更改之前,如何确保没有人更改除产品以外的任何其他字段?

我基本上被撕裂了,因为我不能将审计/更新代码放在 Product 中,而 ProductService 类的更新方法看起来不自然(但是,GetProductById 对我来说似乎很自然)。

我想即使我没有审计要求,我仍然会遇到这些问题。无论哪种方式,我都想限制在一个类中可以更改哪些字段,而不是在网站和 Web 服务中复制逻辑。

我的设计模式一开始是不是很糟糕,还是我可以以一种干净的方式使这项工作?

任何见解将不胜感激。

最佳答案

我将存储库分为两个接口(interface),一个用于读取,一个用于写入。

读取实现 IDisposeable,并在其生命周期内重用相同的数据上下文。它将 linq 生成的实体对象返回给 SQL。例如,它可能看起来像:

interface Reader : IDisposeable
{
    IQueryable<Product> Products;
    IQueryable<Order> Orders;
    IQueryable<Customer> Customers;
}

iQueryable 很重要,所以我得到了 linq2sql 的延迟评估优点。这很容易用 DataContext 实现,而且很容易伪造。请注意,当我使用此接口(interface)时,我从不使用相关行的自动生成字段(即,直接使用 order.Products 不公平,调用必须加入适当的 ID 列)。这是一个限制,我不介意考虑它使伪造单元测试的读取存储库变得多么容易。

写入的每个写入操作使用单独的数据上下文,因此它不实现 IDisposeable。它不将实体对象作为输入或输出 - 它采用每个写入操作所需的特定字段。

当我编写测试代码时,我可以将可读接口(interface)替换为使用一堆我手动填充的 List<> 的假实现。我使用模拟作为写接口(interface)。到目前为止,这就像一个魅力。

不要养成传递实体对象的习惯,它们绑定(bind)到数据上下文的生命周期,这会导致存储库与其客户端之间的不幸耦合。

关于asp.net-mvc - 使用 LINQ2SQL 限制对特定字段的更改时的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1365218/

相关文章:

c# - Linq:返回大型数据集的结果计数

c# - 批量插入和更新性能 C# "ADO.NET"Vs "Linq2SQL"Vs "EF-DataFirst approach"

java - 让 Java 代码更加通用

oop - 构建对象 - 静态构建器方法与构建器类与扩展方法

oop - 工厂模式是否违反了 "Tell, Don' t Ask”原则?

javascript - 使用 MVC 在 razor 页面之间传递具有不同模型的变量。

asp.net - 为什么所有 ASP.NET MVC 网站都允许并忽略任何 URL 前面的字符串 "/(F())/"?

asp.net-mvc - 从 Controller 内部使用 Html.ActionLink 和 Url.Action(...)

c# - 错误帮助 : Out Of Bounds

c# - MVC Mini Profiler - LINQ 开销