Estoy desarrollando un proyecto utilizando ASP MVC y procedimientos almacenados (SQL Server), quiero almacenar elementos de casilla marcada en la base de datos. Intenté agregar un tipo List<string> en el modelo para acceder a estos valores y luego almacenarlos en la base de datos.

El problema es que las bases de datos relacionales están diseñadas específicamente para almacenar un valor por combinación de fila / columna. Para almacenar más de un valor, debo serializar mi lista en un solo valor para el almacenamiento, luego deserializarla al recuperarla.

Esa es mi marca de vista:

               <h6>Items</h6>
                    <ul>
                        <li>
                            <label class="anim">
                                <input type="checkbox" class="checkbox" value="Soups" name="Items">
                                <span>Soups</span>
                            </label>
                        </li>
                        <li>
                            <label class="anim">
                                <input type="checkbox" class="checkbox" value="Burger" name="Items" >
                                <span>Burger</span>
                            </label>
                        </li>
                        <li>
                            <label class="anim">
                                <input type="checkbox" class="checkbox" value="Drinks" name="Items">
                                <span>Drinks</span>
                            </label>
                        </li>
                        <li>
                            <label class="anim">
                                <input type="checkbox" class="checkbox" value="Desserts" name="Items">
                                <span>Desserts</span>
                            </label>
                        </li>
                    </ul>

Método AddBestellung:

try
{
    using (SqlConnection con = new SqlConnection(Connection()))
    {
        using (SqlCommand cmd = new SqlCommand("AddNewBestellung", con))
        {
            foreach(var item in bs.Items)
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@Items", item);
            }

            // Another saved parameters...

            con.Open();
            int i = cmd.ExecuteNonQuery();
            con.Close();

            if (i >= 1)
                return true;
            else
                return false;
        }
    }
}
catch(Exception ex)
{
    string e = ex.Message;
    return false;
}

private static string Connection()
{
    return ConfigurationManager.ConnectionStrings["deliverycon"].ToString();
}

Modelo:

public List<string> Items { get; set; }
0
Exact 17 oct. 2017 a las 15:01

3 respuestas

La mejor respuesta

Enumeración de Banderas -

[Flags]
public enum ItemStorage
{
    Soups = 1,
    Burger = 2,
    Drinks = 4,
    Dessert = 8,
    Cheese = 16
}

Agregué el queso solo para enfatizar la naturaleza binaria de la enumeración de banderas.

Y aquí está tu otro código:

public class Stuff
{
    private List<string> Items;
    private static string Connection()
    {
        return ConfigurationManager.ConnectionStrings["deliverycon"].ToString();
    }

    public bool DoStuff()
    {
        try
        {
            using (SqlConnection con = new SqlConnection(Connection()))
            {
                using (SqlCommand cmd = new SqlCommand("AddNewBestellung", con))
                {

                    cmd.Parameters.AddWithValue("@Items", (int)ConstuctEnumValueFromList(Items));
                    //other saved parameters...

                    con.Open();
                    int i = cmd.ExecuteNonQuery();
                    con.Close();

                    if (i >= 1)
                        return true;
                    else
                        return false;
                }
            }
        }
        catch (Exception ex)
        {
            string e = ex.Message;
            return false;
        }
    }

    private ItemStorage ConstuctEnumValueFromList(List<string> list)
    {
        var result = new ItemStorage();
        if (list.Any())
        {
            var separatedList = string.join(",", list)
            bool success = Enum.TryParse<ItemStorage>(separatedList, out result)
        }
        return result;
    }
}

En este caso, simplemente puede almacenar el campo Elementos como un solo entero y volver a convertirlo en Elemento Almacenamiento cuando se recupere de esta manera:

int i = 1 + 2 + 4 + 8;
var items = (ItemStorage)i;
Console.WriteLine(items.ToString());

Esto debería darle "Sopas, hamburguesas, bebidas, postres";

0
Rich Bryant 18 oct. 2017 a las 08:56

Serialización XML

Primero, asegúrese de estar familiarizado con este documento. Este método requiere que almacene su colección de Artículos en una columna XML en SQL Server. También tiene la ventaja de que puede consultar esa columna, siempre que no tenga miedo de SQLXML y XPath. Muchos desarrolladores lo son.

Una vez que tienes eso, todo se ve muy similar (aunque un poco más simple).

public class Stuff
{
    private List<string> Items;
    private static string Connection()
    {
        return ConfigurationManager.ConnectionStrings["deliverycon"].ToString();
    }

    public bool DoStuff()
    {
        try
        {
            using (SqlConnection con = new SqlConnection(Connection()))
            {
                using (SqlCommand cmd = new SqlCommand("AddNewBestellung", con))
                {

                    cmd.Parameters.AddWithValue("@Items", ConstructXmlFromList(Items));
                    //other saved parameters...

                    con.Open();
                    int i = cmd.ExecuteNonQuery();
                    con.Close();

                    if (i >= 1)
                        return true;
                    else
                        return false;
                }
            }
        }
        catch (Exception ex)
        {
            string e = ex.Message;
            return false;
        }
    }

    public static T FromXML<T>(string xml)
    {
        using (var stringReader = new StringReader(xml))
        {
            var serializer = new XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(stringReader);
        }
    }

    public string ToXML<T>(T obj)
    {
        using (var stringWriter = new StringWriter(new StringBuilder()))
        {
            var xmlSerializer = new XmlSerializer(typeof(T));
            xmlSerializer.Serialize(stringWriter, obj);
            return stringWriter.ToString();
        }
    }

    private string ConstructXmlFromList(List<string> list)
    {
        return ToXML(list);
    }
}

Y nuevamente, es fácil rehidratar el fragmento XML en el List<string> con el que comenzó. Simplemente usarías

var myList = FromXML<List<string>>(fieldValue);
0
Rich Bryant 17 oct. 2017 a las 13:28

No debe serializar / deserializar. Será doloroso usarlo después.

Imagine que necesita recuperar objetos que tienen los elementos 1 y 5 marcados. Si se serializa como una cadena, es menos eficiente y fácil que almacenarlo de la siguiente manera.

Supongamos que tiene una tabla de "Persona" y desea consultar la lista de "Consolas" que posee.

Tendrá la tabla persona :

  • id int clave principal
  • Nombre varchar no nula

Y la mesa consola

  • id int clave_primaria
  • Nombre varchar no nula

Y la mesa para almacenar la consola que poseía:

propiedad_consola

  • id int clave principal
  • person_id int (clave externa => persona (id))
  • console_id int (clave externa => consola (id))

En su código, insertará un registro por casilla de verificación marcada.

Persona:

  • (1) Thomas
  • (2) Pierre

Consola:

  • (1) NES
  • (2) MegaDrive
  • (3) NeoGeo

Propiedad_consola:

  • (1) (1)
  • (1) (2)
  • (1) (3)

  • (2) (1)

  • (2) (1)

Y luego puedes hacer cosas como:

SELECT * 
FROM   person p
INNER  JOIN owned_console oc
ON     p.id = oc.person_id
WHERE  oc.console_id IN (3,1);
1
Thomas 17 oct. 2017 a las 22:11