【问题标题】:How to store multiple checked Checkbox values in DB using ASP.NET MVC如何使用 ASP.NET MVC 在数据库中存储多个选中的复选框值
【发布时间】:2018-03-29 02:48:30
【问题描述】:

我正在使用 ASP MVC 和存储过程 (SQL Server) 开发一个项目,我想将选中的复选框项目存储在数据库中。我尝试在模型中添加List<string> 类型,以便访问这些值,然后将它们存储在数据库中。

关系数据库专门设计为每行/列组合存储一个值的问题。为了存储多个值,我必须将我的列表序列化为一个值进行存储,然后在检索时将其反序列化。

这是我的视图标记:

               <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>

方法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();
}

型号:

public List<string> Items { get; set; }

【问题讨论】:

  • 你可以尝试使用标志枚举msdn.microsoft.com/en-us/library/…
  • 实际上,由于您使用的是 SQL Server,您还可以将复选框值数组存储为 XML。
  • 以及 sql 数据类型如何
  • @RichBryant 谢谢,但你能解释一下它是如何作为 XML 的
  • 好的,我会把这两个选项都作为答案,你可以试试。

标签: c# sql-server asp.net-mvc stored-procedures


【解决方案1】:

您不应该序列化/反序列化。以后用起来会很痛苦。

假设您需要检索已选中第 1 项和第 5 项的对象。 如果将其序列化为字符串,则按如下方式存储它会降低效率和容易度。

假设您有一个“Person”表,并且您想查看他们拥有的“控制台”列表。

您将拥有 person 表:

  • id int 主键
  • 名称 varchar 不为空

和表控制台

  • id int primary_key
  • 名称 varchar 不为空

以及存储控制台拥有的表:

owned_console

  • id int 主键
  • person_id int (外键 => person(id))
  • console_id int(外键 => 控制台(id))

在您的代码中,您将为每个选中的复选框插入一条记录。

人:

  • (1)托马斯
  • (2)皮埃尔

控制台:

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

owned_console:

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

  • (2)(1)

  • (2)(1)

然后您可以执行以下操作:

SELECT * 
FROM   person p
INNER  JOIN owned_console oc
ON     p.id = oc.person_id
WHERE  oc.console_id IN (3,1);

【讨论】:

  • 谢谢,但是创建新表有点复杂,我只想在一列中存储多个,
  • 我不同意,这很简单。见其他答案。接下来我将序列化为 XML,这样您也可以看到这也很容易。
  • @Exact:这IS适当的关系方式做事。您应该永远将多个值存储到单个单元格中 - 只需对单元格中的逗号分隔值说 NO! - 您将看着路上的维修噩梦!正确行事 - 从头开始​​!
  • @Thomas: Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 proper ANSI JOIN 语法在 ANSI-92 SQL 标准中(25 年前!),不鼓励使用它
  • @Exact:存储多个值的正确的关系方式是一个单独的表(每个值一行),它处理单个实体的“多个值”
【解决方案2】:

标志枚举 -

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

我添加 Cheese 只是为了强调 Flags 枚举的二进制性质。

这是你的其他代码 -

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;
    }
}

在这种情况下,您可以简单地将 Items 字段存储为单个整数,并在检索时将其转换回 ItemStorage -

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

这应该给你 “汤、汉堡、饮料、甜点”;

【讨论】:

  • 谢谢,我必须在模型中编写标志枚举?
  • 或者只是一个整数值。两者都可以。
  • 好的,我会尽力让你知道
  • 根据您的建议,当我检查超过 1 个值时,只有第一个检查的值存储在 DB 中
  • 这很有趣。尝试在 ConstuctEnumValueFromList(List list) 方法中放置一个断点并单步执行。
【解决方案3】:

XML 序列化

首先,确保您熟悉this document。此方法要求您将 Items 集合存储到 SQL Server 中的 XML 列。如果您不害怕 SQLXML 和 XPath,它还具有可以查询该列的优点。许多开发人员都是。

一旦你有了它,一切看起来都非常相似(如果稍微简单一点的话)。

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);
    }
}

同样,很容易将 XML 片段重新合成为您开始使用的 List&lt;string&gt;。您只需使用

var myList = FromXML<List<string>>(fieldValue);

【讨论】:

    猜你喜欢
    • 2011-08-21
    • 2016-02-20
    • 2017-09-05
    • 2011-08-12
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    相关资源
    最近更新 更多