What is the correct way to declare a method thread and prevent the same method from being used out of scope?

5

In my last questions I was creating some methods to automate some queries. It's cool, but now I need to control access to methods by specifying a sequence.

When using the Select () method, I can not access it again. After the Where () method I can not access the LeftJoin () and InnerJoin () methods. This is until the ToList () method is reached definitively;

My class will work by creating sql commands in a chained way like Linq to Lambda.

So:

var pessoas = pessoaDAO.Select()
    .LeftJoin(x => x.Telefones, (telefones, pessoa) => telefones.PessoaId == pessoa.Id)
    .Where(x => x.Ativo)
    .OrderBy(x => x.Nome)
    .ToList();

It would be wrong to allow this:

var pessoas = pessoaDAO
    .Select(x => 
        x.Id, 
        x => x.Pessoa, 
        x => x.Ativo,
        x => x.Telefones)
    .Where(x => x.Ativo)
    .Select()
    .ToList();

That is, a Select () after a Where () and even a Select () p>

To solve this, I am trying to separate the methods by interface. So:

public interface IQueryBuilder<TModel> : ICustomQueryBuilder<TModel>
    where TModel : class
{
    ICustomQueryBuilder<TModel> Select();
    ICustomQueryBuilder<TModel> Select(params Expression<Func<TModel, object>>[] members);
}

public interface ICustomQueryBuilder<TModel> : 
    IQueryBuilderJoin<TModel>, 
    IQueryBuilderFilter<TModel>, 
    IQueryBuilderOrder<TModel>, 
    IQueryBuilderExecute<TModel>
    where TModel : class
{        
}
IQueryBuilder that will be the interface used to implement my class inherits from ICustomQueryBuilder , and the Select () methods return the ICustomQueryBuilder type so that so I can not access the Select () method again.

IQueryBuilder inherits from ICustomQueryBuilder and this from other interfaces because I need to have a type implemented in the class to make the return.

Already, ICustomQueryBuilder inherits from:

public interface IQueryBuilderJoin<TModel> : 
    IQueryBuilderFilter<TModel>, 
    IQueryBuilderOrder<TModel>, 
    IQueryBuilderExecute<TModel>
    where TModel : class
{
    IQueryBuilderJoin<TModel> LeftJoin<TMemberJoin>(
        Expression<Func<TModel, TMemberJoin>> member, 
        Expression<Func<TMemberJoin, TModel, bool>> filter);

    IQueryBuilderJoin<TModel> LeftJoin<TMemberJoin>(
        Expression<Func<TModel, IEnumerable<TMemberJoin>>> member, 
        Expression<Func<TMemberJoin, TModel, bool>> filter);

    IQueryBuilderJoin<TModel> InnerJoin<TMemberJoin>(
        Expression<Func<TModel, TMemberJoin>> member, 
        Expression<Func<TMemberJoin, TModel, bool>> filter);

    IQueryBuilderJoin<TModel> InnerJoin<TMemberJoin>(
        Expression<Func<TModel, IEnumerable<TMemberJoin>>> member, 
        Expression<Func<TMemberJoin, TModel, bool>> filter);
}

Following:

public interface IQueryBuilderFilter<TModel> : IQueryBuilderOrder<TModel>
    where TModel : class
{
    IQueryBuilderFilter<TModel> Where(Expression<Func<TModel, bool>> filter);
}

public interface IQueryBuilderOrder<TModel> : IQueryBuilderExecute<TModel>
    where TModel : class
{
    IQueryBuilderOrder<TModel> OrderBy(params Expression<Func<TModel, object>>[] members);
    IQueryBuilderOrder<TModel> OrderByDesc(params Expression<Func<TModel, object>>[] members);
}

public interface IQueryBuilderExecute<TModel>
    where TModel : class
{
    List<TModel> ToList();
}

Finally, you would have:

public class QueryBuilder<TModel> : IQueryBuilder<TModel>
    where TModel : class
{
   // ... implementações
}

Is it correct to do this type of implementation?

To better illustrate the need for return, eg:

public class PessoaDAO : GenericDAO<Pessoa>
{
    // ... outros métodos

    public IQueryBuilderFilter<Pessoa> Where(Expression<Func<TModel, bool>> filter)
    {
       // ... implementações
       return this;
    }

    // ... outros métodos 
}

In other words, this is necessary for concatenating the methods and the type must be a type already implemented, otherwise the automatic cast will not be accepted.

    
asked by anonymous 14.11.2014 / 21:12

1 answer

2

Is it correct to do this type of implementation?

From the point of view of the implementation objective only, yes. By the way, I would say that this is the (elegant) performance way of allowing or not the chaining of the methods.

However, I believe that this organization may characterize a loss of functionality. There is nothing wrong with allowing OrderBy() after Where() , or Where() after Select() . I understand that the standardization is to leave the set of extension methods more like an ANSI SQL language, but the idea of extension methods is not to approach SQL: the idea is to work with the agnostic manipulation of sets.

    
14.11.2014 / 22:24