2011-06-08 677 views
5

Estoy trabajando con una muestra de código, y solo quiero escuchar algunas opiniones sobre la forma en que han hecho las cosas. Usan el viejo y simple ADO.NET. Tienen una función genérica llamada Lectura que devuelve 1 registro. Aquí está el código:Creando un método de recuperación genérico para devolver 1 registro

public static T Read<T>(string storedProcedure, Func<IDataReader, T> make, object[] parms = null) 
{ 
    using (SqlConnection connection = new SqlConnection()) 
    { 
     connection.ConnectionString = connectionString; 

     using (SqlCommand command = new SqlCommand()) 
     { 
     command.Connection = connection; 
     command.CommandType = CommandType.StoredProcedure; 
     command.CommandText = storedProcedure; 
     command.SetParameters(parms); 

     connection.Open(); 

     T t = default(T); 
     var reader = command.ExecuteReader(); 
     if (reader.Read()) 
      t = make(reader); 

     return t; 
     } 
    } 
} 

No sé por qué:

  • Ellos usan Func<IDataReader, T> make como parte de la firma del método? ¿Es eficiente hacerlo así? ¿Hay una mejor forma/mejor práctica para hacer esto?
  • No entiendo T t = default(T);? ¿Es eficiente hacerlo así? ¿Hay una mejor forma/mejor práctica para hacer esto?
  • ¿Qué hace t = make(reader);? ¿Es eficiente hacerlo así? ¿Hay una mejor forma/mejor práctica para hacer esto?

La función de llamada sería algo como esto:

public Customer GetCustomer(int customerId) 
{ 
    // Other code here 
    string storedProcedure = "MyStoredProcedure"; 
    object[] parameters = { "@CustomerId", customerId }; 
    return Db.Read(storedProcedure, Make, parameters); 
} 

private static Func<IDataReader, Customer> Make = reader => 
new Customer 
{ 
    CustomerId = reader["CustomerId"].AsId(), 
    Company = reader["CompanyName"].AsString(), 
    City = reader["City"].AsString 
}; 

No entiendo la parte Func Make? ¿Puede alguien explicarme por favor lo que está sucediendo aquí y si esto es buenas prácticas? Cualquier cambio sería apreciado, pero proporcione el código de muestra detallado :)

Respuesta

3

El delegado para el make (materialización) es bastante versátil y flexible, pero IMO hace un poco de trabajo innecesario en la gran mayoría de los casos. En términos de lo que hace - utilizan el delegado como devolución de llamada para que la persona que llama especifique cómo leer el registro.

Tenga en cuenta, ya que no esperan que el consumidor cambio de registro, que probablemente se debe exponer IDataRecord, no IDataReader (cualquier lector también implementa registro).

Tenga en cuenta que si hay mensajes de error en la secuencia TDS después de el primer registro, el enfoque que se muestra no los verá, pero se trata de un caso marginal. Si quería para mitigar contra de eso, se podía leer hasta el final de la secuencia TDS:

while(reader.NextResult()) {} 

Personalmente, sin embargo, yo sólo tiene que utilizar pulcro-punto-net aquí - evita tener que escribir ese tipo por código de forma manual:

var cust = connection.Query<Customer>("MyStoredProcedure", 
    new { CustomerId = customerId }, 
    commandType: CommandType.StoredProcedure).Single(); 

este MyStoredProcedure ejecuta como un procedimiento almacenado, pasando @CustomerId con el valor de customerId, a continuación, se aplica una columna directa < ===> partido de la propiedad/campo para crear Customer registros, a continuación, afirma que existe exactamente un resultado, y lo devuelve.

2

Utilizan Func make como parte de la firma del método? ¿Es eficiente hacerlo así? ¿Hay una mejor forma/mejor práctica para hacer esto?

Debido a la naturaleza genérica del método T es desconocida por lo que no saben cómo asignar al lector a T propiedades. Entonces dejan esta responsabilidad a la persona que llama del método. En realidad, esto es lo suficientemente eficiente y es una buena práctica.

No entiendo T t = predeterminado (T) ;? ¿Es eficiente hacerlo así? ¿Hay una mejor forma/mejor práctica para hacer esto?

Dado que T puede ser de valor o de tipo de referencia no se puede asignar a nulo. default(T) devuelve el valor predeterminado para este tipo. En el caso del tipo de referencia, será nulo. En el caso de un tipo de valor, por ejemplo, entero, será 0.

Qué hace t = make (reader); ¿hacer? ¿Es eficiente hacerlo así? ¿Hay una mejor forma/mejor práctica para hacer esto?

Invoca el delegado que se pasa y asigna el resultado al t.

Cuestiones relacionadas