2010-09-16 7 views
8

Quiero crear un tipo complejo para usar dentro de un administrador de entidades desde una consulta construida dinámicamente y ejecutada con exec(). ¿Es posible?; ya que estoy escribiendo un filtro, ¿qué harías si no fuera posible?Cómo crear un tipo complejo a partir de un procedimiento almacenado que usa exec()?

Además, estoy evaluando el uso de linq, pero el filtro necesita muchas tablas y sus registros, por lo tanto, la eficiencia es una preocupación.

Gracias ...

+0

Tengo curiosidad ¿este exec() devuelve múltiples conjuntos de registros o solo uno? – Markis

+0

ejecuta un comando sql en un procedimiento tsql – JPCF

+0

Este tipo de consulta es exactamente para lo que LINQ2EF es. Cuando 'ejecutas' en el servidor, ya no solo estás perdiendo los beneficios de la precompilación, sino que también pierdes los beneficios de los planes de ejecución en caché que obtienen las consultas parametrizadas. – JustLoren

Respuesta

4

Sí, puede utilizar Entity Framework y LINQ 4 en la parte superior, se genera la consulta parametrizada y lo ejecuta, esa es la opción.

Otra opción es (y lo hice varias veces) para crear una clase base/interfaz, digamos:

public interface IExecutable 
{ 
    void Execute(IConnection connection); 
} 
public interface IExecutable<TResult> : IExecutable 
{ 
    TResult Result { get; } 
} 

public abstract ActionBase<TResult> : IExecutable<TResult> 
{ 
    protected void AddParameter(....); 

    protected IDataReader ExecuteAsReader(string query) { 
     //create a DB Command, open transaction if needed, execute query, return a reader. 
    } 

    protected object ExecuteAsScalar(string query) { 
     //.... 
    } 

    //the concrete implementation 
    protected abstract TResult ExecuteInternal(); 

    IExecutable.Execute(IConnection connection) { 
     //keep the connection 
     this.Result = ExecuteInternal(); 
    } 

    //another common logic: 

} 

continuación, puede crear sus acciones concretas:

public sealed class GetUsersAction : ActionBase<<IList<User>> 
{ 
    //just a constructor, you provide it with all the information it neads 
    //to be able to generate a correct SQL for this specific situation 
    public GetUsersAction(int departmentId) { 
     AddParameter("@depId", departmentId); 
    } 

    protected override IList<User> ExecuteInternal() { 
     var command = GenerateYourSqlCommand(); 

     using(var reader = ExecuteAsReader(command)) { 
      while(reader.Read) { 
       //create your users from reader 
      } 
     } 
     //return users you have created 
    } 
} 

Muy fácil crear acciones concretas!

Entonces, para que sea aún más fácil, crear una ExecutionManager cuya preocupación es cómo conseguir la conexión y ejecuta la acción:

public sealed ExecutionManager() { 

    TResult Execute<TResult>(IExecutable<TResult> action) { 
     var connection = OhOnlyIKnowHowTOGetTheConnectionAnfHereItIs(); 
     action.Execute(connection); 
     return action.Result; 
    } 
} 

Ahora sólo lo utilizan:

var getUsersAction = new GetUsersAction(salesDepartmentId); 

//it is not necessary to be a singletone, up to you 
var users = ExecutionManager.Instance.Execute(getUsersAction); 

//OR, if you think it is not up to ExecutionManager to know about the results: 
ExecutionManager.Instance.Execute(getUsersAction); 
var users = getUsersAction.Result 

Usando este sencillo técnica es muy fácil mover toda la conexión/comando/lógica de ejecución de las acciones concretas a la clase base, y las preocupaciones de las acciones concretas son simplemente generar SQL y convertir la salida de la base de datos en algunos resultados significativos.

Buena suerte :)

+0

Hmmm ... sí ... pero directamente sobre el DB ... Estoy preguntando esto porque queremos que los procedimientos almacenados estén completamente contenidos en la base de datos. – JPCF

1

Si usted decide ir a la ruta de LINQ y está buscando una buena manera de hacer el filtrado. LinqKit es una gran biblioteca para crear predicados ad-hoc. El problema con la biblioteca de linq incorporada es que solo se pueden combinar sentencias AND ad-hoc, no se pueden combinar sentencias OR ad-hoc. Linqkit lo hace muy fácil de lograr.

Cuestiones relacionadas