实体框架查询SPA

时间:2014-07-07 07:48:19

标签: c# sql entity-framework

我是SPA和实体框架的新手,我有一个关于正确/首选方式的问题。

我有一个网页可以通过一些过滤器搜索客户(如姓名,姓氏,生日,电话号码)。

使用ajax,我从View传递给一个ViewModel对象,如下所示:

public class CustomerSearch
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public DateTime? Birthday{ get; set; }
    public string Phone{ get; set; }
}

进入控制器我有这种搜索方法:

 public List<CustomerList> GetCustomersList(CustomerSearch cs)
    { ..... }

在我的应用程序中,还有DataAccess对象。

现在,问题是:如何在智能模式下对数据库进行查询?

我认为有些情况,但我不知道哪种情况最适合分层。

  1. 我可以要求为IQueryable对象建模并执行Where条件到控制器
  2. 我可以使用参数
  3. 等过滤器创建DataAccess方法
  4. 我可以创建一个填充了filters值的Customer对象(模型对象),并将其传递给执行查询的模型
  5. 哪种方法最好?

    提前致谢。

    丹尼尔

1 个答案:

答案 0 :(得分:0)

我建议您提出第一个选项,原因如下:

  • 如果可能的搜索查询数量增加,您的第二个选项可能需要很多参数。通常不建议使用大量参数,因为它会导致可读性问题。 (例如,调用具有30个参数的方法)

  • 您的第三个选项将无法创建像'1998年的BirthDate'或'Surname以Q开头'的查询。

通过专门为查询目的创建一个类,您可以执行以下操作:

public class CustomerQuery
{
    public string Name { get; set; }
    public DateTime? BirthDay { get; set; }

    internal IQueryable<Customer> Apply(IQueryable<Customer> query)
    {
        var result = query;
        if (!string.IsNullOrWhiteSpace(Name))
        {
            result = result.Where(c => c.Name == Name);
        }

        if (BirthDay.HasValue)
        {
            result = result.Where(c => c.BirthDay == BirthDay.Value);
        }
        return result;
    }
}

特别注意internal方法的Apply可见性。如果在数据访问层中定义此类并且这是在单独的C#项目中定义的,则Apply方法仅对此数据访问层可见,而不对GUI项目可见。

调用它将是:

public List<Customer> GetCustomersList(CustomerQuery customerQuery)
{
    using (var context = new MyDbContext())
    {
        var customers = context.Customers;
        return customerQuery.Apply(customers).ToList();
    }
}

这可以进一步扩展到支持例如不同类型的字符串搜索(包含,StartsWith等):

public enum TextFilterType
{
    StartsWith,
    EndsWith,
    Contains,
    ExactMatch
}

public class StringQuery
{
    private readonly string _value;
    private readonly TextFilterType _filterType;

    public StringQuery(string value, TextFilterType filterType)
    {
        _value = value;
        _filterType = filterType;
    } 

    public string Value
    {
        get { return _value; }
    }

    public TextFilterType FilterType
    {
        get { return _filterType; }
    }
}

如果我们将其应用于CustomerQuery类型:

public class CustomerQuery
{
    public StringQuery Name { get; set; }
}

然后,您查看FilterType的{​​{1}}属性,了解是否需要执行StringQueryContains等。