C# 如何在不反复重复代码的情况下遍历notnull的读取器
首先,我刚开始编程,尤其是C语言,谢谢你的帮助 我有一个静态web表单,大多数复选框中有大约150个表单对象。我决定在sql db中为每个表单提交一条记录。例如,问题X有5个复选框可供选择。这5个复选框中的每一个在数据库中都有一列 我已经完成了post页面的工作,正在构建一个编辑页面,在那里我加载记录,然后填充表单 我是如何做到这一点的,通过将存储的proc传递id,然后将所有返回的列值放入相应的对象属性中,然后将asp控件对象设置为它们 将asp控件设置为选定值的示例:C# 如何在不反复重复代码的情况下遍历notnull的读取器,c#,asp.net,ado.net,C#,Asp.net,Ado.net,首先,我刚开始编程,尤其是C语言,谢谢你的帮助 我有一个静态web表单,大多数复选框中有大约150个表单对象。我决定在sql db中为每个表单提交一条记录。例如,问题X有5个复选框可供选择。这5个复选框中的每一个在数据库中都有一列 我已经完成了post页面的工作,正在构建一个编辑页面,在那里我加载记录,然后填充表单 我是如何做到这一点的,通过将存储的proc传递id,然后将所有返回的列值放入相应的对象属性中,然后将asp控件对象设置为它们 将asp控件设置为选定值的示例: questionX.I
questionX.Items[0].Selected = selectedForm.questionX0
questionX.Items[1].Selected = selectedForm.questionX1
questionX.Items[2].Selected = selectedForm.questionX2
正如你所看到的,这是非常令人厌倦的,因为有超过150个这样做。另外,我刚刚发现如果响应为NULL,那么我得到的错误是它不能转换为字符串。因此,我添加了这行代码来克服它:
这是我将返回的列值填充到对象属性中的部分。对象属性实体是:
if (!String.IsNullOrEmpty((string)reader["questionX0"].ToString()))
{entity.patientUnderMdTreatment = (string)reader["questionX0"];}
因此,不必将if-then语句添加150多次。必须有一种更有效的方法。我建议使用。它消除了这个问题。这是一种快速简便的方法。。有一些关于调查LINQ的建议,我首先同意这些建议
for (int i = 0; i < 150; i++)
{
if (!String.IsNullOrEmpty((string)reader["questionX" + i.ToString()].ToString()))
{entity.patientUnderMdTreatment = (string)reader["questionX" + i.ToString()];}
}
行首先,您似乎在使用string.IsNullOrEmptyvalue,但这不会检查数据为null时从数据库返回的特殊DBNull值。您应该使用更类似于value is DBNull的东西 你剩下的问题听起来很复杂,所以如果我的答案也很复杂,请不要拖延。我个人会使用自定义属性: 声明自定义属性 以下是一个框架,让你的想法。您可能希望在VisualStudio中使用“属性”代码段来了解有关如何声明这些属性的更多信息
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class QuestionColumnAttribute : Attribute
{
public string ColumnName { get; private set; }
public QuestionColumnAttribute(string columnName)
{
ColumnName = columnName;
}
}
在实体类中使用自定义属性
在声明实体类的地方,将此自定义属性添加到每个字段,例如,在声明patientUnderMdTreatment的地方:
[QuestionColumn("questionX0")]
public string patientUnderMdTreatment;
在字段上迭代
迭代字段,而不是迭代读取器中的列。对于每个具有QuestionColumnAttribute的字段,从读取器获取相关列:
foreach (var field in entity.GetType().GetFields())
{
var attributes = field.GetCustomAttributes(typeof(QuestionColumnAttribute), true);
if (attributes.Length == 0)
continue;
object value = reader[attributes[0].ColumnName];
if (!(value is DBNull))
field.SetValue(entity, value.ToString());
}
对于问题的第一部分,在设置ASP控件时,可以使用类似的策略迭代selectedForm的字段,这可能更简单,因为您不需要自定义属性-只需选择名称以“questionX”开头的字段即可。因此我听到两个问题:
-如何处理来自IDataReader的null?
-如何处理多个字段
让我们从一个简单的开始。定义自己的助手方法:
public static T IsDbNull<T>(object value, T defaultValue)
{
return (T)(value is DBNull ? defaultValue : value);
}
然后使用它:
entity.patientUnderMdTreatment = IsDbNull<string>(reader["question"], null);
现在,如何将实体字段映射到表单?这真的取决于你。您可以硬编码它,也可以使用反射。运行时映射与编译时的差异可能与您的情况完全无关。
如果表单字段的名称与数据库中的名称相同,则会有所帮助,因此您不必像Timwi的文章中那样在表单字段上进行名称映射,但最终您可能会发现您必须对其中许多字段进行验证/规范化,此时硬编码才是您真正需要的,由于没有一种方法可以根据不断变化的规范动态生成逻辑。无论您是否必须重命名150 db字段或附加150个属性,最终都是一种On解决方案,其中n是字段数
我仍然有点不确定为什么需要读回数据。如果由于验证错误而需要在表单重新加载时保留用户的输入?从请求中重新加载它们不是更容易/更好吗?实体和selectedForm是否也是相同的对象类型?我假设它不是db实体,否则为什么要使用reader呢
你可能会走一些捷径,但我很难理解你在读什么和写什么,以及什么时候读什么。大约150个表单对象,一定是很棒的用户体验,哈?哈,我同意,但不能拍摄messenger。我认为Antoni不想将所有值分配给同一个字段实体。patientUnderMdTreatment。我将进一步研究并尝试此方法out@Antoni我已经用了很多年了,这是一个很好的解决方案。
entity.patientUnderMdTreatment = IsDbNull<string>(reader["question"], null);