Manera más eficiente de acceder a múltiples columnas de la base de datos

Estoy buscando una forma más eficiente de crear una lista delimitada por punto y coma de varias columnas de base de datos. El código que estoy usando ahora se ve así (y funciona):

//Process List of things
var things = DB.DbColumn_1.HasValue ? DB.DbColumn_1.Value.Equals(true) ? "thing 1;" : "" : "");
things += DB.DbColumn_2.HasValue ? DB.DbColumn_2.Value.Equals(true) ? "thing 2;" : "" : "");
things += DB.DbColumn_3.HasValue ? DB.DbColumn_3.Value.Equals(true) ? "thing 3;" : "" : "");
things += DB.DbColumn_4.HasValue ? DB.DbColumn_4.Value.Equals(true) ? "thing 4;" : "" : "");
// Remove final ';' from thing list if non-empty
things = things.Length > 0 ? things.Substring(0, things.Length-1) : things;

De hecho, tengo alrededor de 8 columnas para procesar; el ejemplo le ahorra algo de eso. Así que tengo un gran bloque feo de código para construir una cadena simple. Aunque esto parece funcionar bien, parece demasiado código para lo que estoy tratando de hacer. Además, ¿debo tener cuidado al usar ".Equals ()" en esta situación?

Después de una lluvia de ideas, se me ocurrió nada que pareciera más eficiente que esto, como construir una función separada para crear la cadena en sí. Todas las columnas son bools anulables únicos y todos tienen salidas de cadena únicas para la lista resultante.

¿O estoy accediendo a estos elementos de manera lo suficientemente eficiente como para no preocuparme por eso?

¡Gracias!

preguntado el 03 de mayo de 12 a las 15:05

Flashbacks de El gato en el sombrero. Cosa 1 y cosa 2... -

Puede escribir una consulta que obtenga todos los valores en una sola lectura y luego trabajar con el resultado en linq-to-object para crear la cadena. -

3 Respuestas

DB.DbColumn_1.HasValue && DB.DbColumn_1.Value.Equals(true) es una forma muy dificil de escribir DB.DbColumn_1.GetValueOrDefault(), pero son funcionalmente equivalentes. Ver más información sobre el Nullable<T> estructurabool? es equivalente a Nullable<bool>, que es el tipo de su columna DB) en http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=vs.80).aspx y http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

Puede utilizar uno de estos enfoques:

var sections = new List<string>();
if (DB.DbColumn_1.GetValueOrDefault()) sections.Add("thing 1");
if (DB.DbColumn_2.GetValueOrDefault()) sections.Add("thing 2");
//...other columns
var things = string.Join(";", sections);

o:

var pairs = new List<Tuple<bool?, string>>
{
    Tuple.Create(DB.DbColumn_1, "thing 1"),
    Tuple.Create(DB.DbColumn_2, "thing 2")
    //...other columns
};
var things = string.Join(";", pairs.Where(x => x.Item1.GetValueOrDefault()).Select(x => x.Item2));

O configura los pairs sólo una vez:

static readonly List<Tuple<Func<DBType, bool?>, string>> pairs = new List<Tuple<Func<DBType, bool?>, string>>
    {
        new Tuple<Func<DBType, bool?>, string>(d => d.DbColumn_1, "thing 1"),
        new Tuple<Func<DBType, bool?>, string>(d => d.DbColumn_2, "thing 2")
        //...other columns
    };

void inSomeMethod()
{
    var things = string.Join(";", pairs.Where(x => x.Item1(DB).GetValueOrDefault()).Select(x => x.Item2));
}

Depende de las circunstancias, por supuesto, pero me gusta más el último. Si la verbosidad de la pairs declaración le molesta, (es decir, repetir Tuple<Func<DBType, bool?>, string>) Puedes hacerlo:

class ReadDbBools : Tuple<Func<DBType, bool?>, string>
{
    public ReadDbBools(Func<DBType, bool?> retrieveFunc, string ifTrue) : base(retrieveFunc, ifTrue) { }
}

static readonly List<ReadDbBools> pairs = new List<ReadDbBools>
{
    new ReadDbBools(d => d.DbColumn_1, "thing 1"),
    new ReadDbBools(d => d.DbColumn_2, "thing 2")
    //...other columns
};

contestado el 03 de mayo de 12 a las 16:05

Podría extender un poco su modelo linq-to-sql para devolver el valor que espera, así que eliminó esa parte:

public partial class Entity {
    public string DbColumn_1_Display {
        return (DbColumn_1 ?? false) ? "thing_1" : "";
    }
    /*for each property*/
}

y luego para seleccionarlo puedes hacer algo como esto:

var result = from db in DB
             select new { 
                   c1 = DbColumn_1_Display,  
                   c2 = DbColumn_2_Display /*etc*/};
var string = string.Format("{0};{1};{2}/*...*/", result.c1, result.c2 /*...*/);

No sé si esto facilita las cosas.

contestado el 03 de mayo de 12 a las 15:05

Bueno, para empezar, los tipos anulables anulan el Equals método y así en lugar de esto

DB.DbColumn_1.HasValue ? DB.DbColumn_1.Value.Equals(true) ? "thing 1;" : "" : ""

Puedes escribir esto

DB.DbColumn_1.Equals(true) ? "thing1;" : ""

También usando string.Join es una forma mucho más ordenada de manejar el punto y coma extra al final, lo que te deja con esto:

var things = string.Join(";", new []
    {
        DB.DbColumn_1.Equals(true) ? "thing1" : null,
        DB.DbColumn_2.Equals(true) ? "thing2" : null,
        // etc...
    }.Where(i => i != null));

Esto hace que el código sea más legible, sin embargo, no hará mucho para mejorar el rendimiento, ya que este procesamiento ya debería ser bastante rápido de todos modos.

contestado el 03 de mayo de 12 a las 15:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.