简体   繁体   English

Active Record模式的最佳做法,以及使用静态方法进行组操作

[英]Best practices for Active Record Pattern and using static methods for group operations

It is true what they say about design patterns that they are simply the embodiment of techniques already in general use. 他们对设计模式的评价确实是,它们只是已经普遍使用的技术的体现。 I have been using the Active Record Pattern since 1985. 自1985年以来,我一直在使用Active Record Pattern。

One of the attributes of this pattern is the use of static members in the implementation to perform searches that return collections of the underlying data. 此模式的属性之一是在实现中使用静态成员来执行返回基础数据集合的搜索。

class Customer { 
   static Customer FindCustomerById( int Id ) { ... } 
   static Customer[] FindActiveCustomers() { ... }
}

In many cases where I need much more flexibility I break encapsulation and include a method such as 在很多情况下,我需要更大的灵活性,因此我破坏了封装并加入了诸如

static Customer[] FindCustomers( string criteria ) { ... } 

where one would call it as 人们会称之为

Customer[] customers = Customer.FindCustomers( "LastName = 'Smith'" );

Of course this is a hold over from when I used this pattern in C, is clearly not a best practice, and in the wrong hands can lead to SQL injection and other problems. 当然,这是我在C语言中使用此模式时遇到的问题,显然不是最佳实践,如果使用不当,会导致SQL注入和其他问题。

Is there a suitable pattern or practice that could be applied that would allow the Customer class to become a "criteria" for such a search? 是否有合适的模式或做法可以应用,以使Customer类成为此类搜索的“标准”?

For example suppose I want to find customers whose last name was Smith, I might consider writing an implementation such as: 例如,假设我要查找姓氏为Smith的客户,则可以考虑编写一个实现,例如:

static Customer[] FindCustomers( Customer customer ) { ... }

to be called as (with the appropriate constructor of course): 被称为(当然有适当的构造函数):

Customer[] customersnamedsmith = 
   Customer.FindCustomer( new Customer( "Smith" ) );

Or is it better to create a co-class that would define the criteria? 还是创建一个可以定义条件的共同类更好?

Just from working with LINQ, I like the idea of passing in an expression instead of a string. 仅仅通过使用LINQ,我就喜欢传递表达式而不是字符串的想法。 But, perhaps that is just me? 但是,也许就是我吗? I am also not fond of ActiveRecord, as it mixes state and behavior in the same object. 我也不喜欢ActiveRecord,因为它在同一对象中混合了状态和行为。 Nice packaging, but not a clean separation of model and data access. 包装精美,但没有将模型和数据访问完全分开。

I have seen cases where a customer class is passed to active record, but if you are going that route, a repository pattern is much cleaner and does separate the behavior from state. 我已经看到了将客户类传递到活动记录的情况,但是如果您按照这种路线进行操作,则存储库模式会更加整洁,并且会将行为与状态分开。 I see nothing wrong, however, with using the investment you already have in active record and passing an object. 但是,我认为使用已在活动记录中拥有的投资并传递对象没有错。

If you would like create a criteria class, you will end up with a bit of a strategy pattern, which can make your active record a bit more active than it is today. 如果您想创建一个条件类,那么您将获得一些策略模式,这可以使您的活动记录比今天的活动记录更活跃。 It is an applicable pattern, however, and will also solve any injection issues. 但是,这是适用的模式,并且还将解决任何注入问题。

Take a look at the WWPlatform DataAccess sample on codeplex. 看看codeplex上的WWPlatform DataAccess示例。 It shows an excellent example of providing search specification instances as params albeit through the repository pattern. 它显示了一个很好的示例,尽管通过存储库模式也可​​以将搜索规范实例作为参数提供。

Although it pushes you out of the database level, you could use something similar to a comparator. 尽管它使您脱离数据库级别,但可以使用类似于比较器的功能。 I don't know C#, so I just fudged it, but you get the gist: 我不了解C#,所以我只是捏捏了一下,但您明白了要点:

class CustomerLastNameEvaluator : IEvaluate
{
    private Customer _customer;

    public CustomerLastNameEvaluator (String lastName)
    {
        _customer = new Customer (lastName);
    }

    bool IEvaluate.Evaluate(Customer c)
    {
        return (_customer.LastName == c.LastName);
    }
}

Customer[] customers = Customer.FindCustomers( new CustomerLastNameEvaluator("Smith") );

Without a reason not to, I'd provide a method like this: 没有理由,我会提供这样的方法:

public static IEnumerable<Customer> AllCustomers()
{
   return Customers.AsEnumerable();
}

If you have reasons not to do this, you need to articulate those reasons and examine them in detail in order to design the right solution. 如果您有理由不这样做,则需要阐明这些原因并详细检查它们,以设计正确的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM