我有一个非常简单的映射函数叫做“BuildEntity”,它执行将读取器数据转储到域对象所需的通常无聊的“左/右”编码。 (如下所示)我的问题是这个 - 如果我没有按原样带回这个映射中的每一列,我得到“System.IndexOutOfRangeException”异常,并想知道ado.net是否有任何要纠正的内容,所以我不知道每次调用SQL需要带回每一列...

我真正想要的是像“IsValidColumn”这样的东西,所以我可以在我的DataAccess类中保留这个1映射函数并定义所有左/右映射 - 并且即使sproc没有返回列出的每一列,它也能正常工作。 ..

Using reader As SqlDataReader = cmd.ExecuteReader()
  Dim product As Product
  While reader.Read()
    product = New Product()
    product.ID = Convert.ToInt32(reader("ProductID"))
    product.SupplierID = Convert.ToInt32(reader("SupplierID"))
    product.CategoryID = Convert.ToInt32(reader("CategoryID"))
    product.ProductName = Convert.ToString(reader("ProductName"))
    product.QuantityPerUnit = Convert.ToString(reader("QuantityPerUnit"))
    product.UnitPrice = Convert.ToDouble(reader("UnitPrice"))
    product.UnitsInStock = Convert.ToInt32(reader("UnitsInStock"))
    product.UnitsOnOrder = Convert.ToInt32(reader("UnitsOnOrder"))
    product.ReorderLevel = Convert.ToInt32(reader("ReorderLevel"))
    productList.Add(product)
  End While

===============>>#1 票数:6

另请查看我编写的用于数据命令的扩展方法

public static void Fill<T>(this IDbCommand cmd,
    IList<T> list, Func<IDataReader, T> rowConverter)
{
    using (var rdr = cmd.ExecuteReader())
    {
        while (rdr.Read())
        {
            list.Add(rowConverter(rdr));
        }
    }
}

你可以像这样使用它:

cmd.Fill(products, r => r.GetProduct());

其中“products”是要填充的IList <Product>,“GetProduct”包含从数据读取器创建Product实例的逻辑。 对于没有所有字段存在的这个特定问题,它无济于事,但是如果你正在做很多像这样的老式ADO.NET,它就会非常方便。

===============>>#2 票数:1

使用GetSchemaTable()方法检索DataReader的元数据。 返回的DataTable可用于检查特定列是否存在。

===============>>#3 票数:1

为什么不让每个sproc返回完整的列集,使用null,-1或者没有数据的可接受值。 避免必须捕获IndexOutOfRangeException或重写LinqToSql中的所有内容。

===============>>#4 票数:1 已采纳

尽管connection.GetSchema(“Tables”)确实返回有关数据库中表的元数据,但如果定义任何自定义列,它将不会返回sproc中的所有内容。

例如,如果你输入一些随机ad-hoc列,如* SELECT ProductName,'Testing'作为ProductTestName FROM dbo.Products“,你将不会看到'ProductTestName'作为列,因为它不在Products表的Schema中。要解决此问题,并请求返回数据中的每个列,请利用SqlDataReader对象“GetSchemaTable()”上的方法

如果我将此添加到您在原始问题中列出的现有代码示例中,您会注意到在声明读者之后我添加了一个数据表以从读取器本身捕获元数据。 接下来,我遍历这个元数据,并将每列添加到我在左右代码中使用的另一个表中,以检查每个列是否存在。

更新的源代码

Using reader As SqlDataReader = cmd.ExecuteReader() 
Dim table As DataTable = reader.GetSchemaTable()
Dim colNames As New DataTable()
For Each row As DataRow In table.Rows
 colNames.Columns.Add(row.ItemArray(0))
Next
Dim product As Product  While reader.Read()    
product = New Product()  
If Not colNames.Columns("ProductID") Is Nothing Then
  product.ID = Convert.ToInt32(reader("ProductID"))
End If    
product.SupplierID = Convert.ToInt32(reader("SupplierID"))    
product.CategoryID = Convert.ToInt32(reader("CategoryID"))    
product.ProductName = Convert.ToString(reader("ProductName"))    
product.QuantityPerUnit = Convert.ToString(reader("QuantityPerUnit"))    
product.UnitPrice = Convert.ToDouble(reader("UnitPrice"))    
product.UnitsInStock = Convert.ToInt32(reader("UnitsInStock"))    
product.UnitsOnOrder = Convert.ToInt32(reader("UnitsOnOrder"))    
product.ReorderLevel = Convert.ToInt32(reader("ReorderLevel"))    
productList.Add(product)  
End While

说实话,这是一个黑客,因为你应该返回每一列以正确地保湿你的对象。 但是我想要包含这个阅读器方法,因为它实际上会抓取所有列,即使它们没有在表模式中定义。

当您进入延迟加载方案时,这种将关系数据映射到域模型的方法可能会导致一些问题。

===============>>#5 票数:0

我最终写了自己的,但这个mapper非常好(而且很简单): https//code.google.com/p/dapper-dot-net/

===============>>#6 票数:0

为什么不使用LinqToSql - 您需要的一切都是自动完成的。 为了通用,您可以使用任何其他ORM工具进行.NET

===============>>#7 票数:0

在开始while循环之前,我会为每个字段名称调用reader.GetOrdinal 不幸的是,如果字段不存在, GetOrdinal会抛出IndexOutOfRangeException ,因此它不会非常高效。

您可以将结果存储在Dictionary<string, int>并使用其ContainsKey方法来确定是否提供了字段。

===============>>#8 票数:0

如果你不想使用ORM,你也可以使用反射来做这样的事情(虽然在这种情况下因为ProductID在两边都没有相同的名字,你不能用这里演示的简单方式来做): List C#中的提供者

  ask by translate from so

未解决问题?本站智能推荐:

1回复

使用ado.net将类映射到数据库

我想知道是否存在使用ado.net实体框架从现有类中创建数据库或将现有类映射到数据库的方法。 我寻找了教程,但只找到了使用实体模型设计器创建类的方法。 例如,我有一个类,它的属性为Length和Age 在数据库上,我有一个名为Bird的表,其列为Length和Age 现在
1回复

映射我的对象以用于ADO.NET [重复]

这个问题已经在这里有了答案: 为自定义类型 3答案 创建ADO.NET映射 我收到异常“从对象类型MyType到已知的托管提供程序本机类型不存在映射”。 如何提供映射? 我正在通过ADO.NET将数据发送到SQL Server。 我基本上是将MyType转
6回复

在Ado.net的情况下,DataAccess层返回域对象?

我正在创建一个项目,我将使用ADO.NET作为数据访问层与数据库进行交互。 现在,我非常困惑的是: 1)我应该在这个应用程序中有域对象吗? 2)我的sql查询结果是否应始终与域对象绑定? 3)如果我不使用域对象,那么我是否总是从数据访问层返回自定义模型 ,其中包含我想要在
1回复

Ado.net迭代遍历SqlDataReader行中的每一列

我正在编写一个简单的XML Web服务,并希望返回原始XML。 我这样做是通过创建一个表示XML的字符串文字。 我的数据源是一个SqlDataReader对象,它包含存储的proc调用的结果。 我现在这样做的方法是使用while循环并从item属性中读取值,如下所示: 问题是存储过
1回复

ADO.NET锁定对象

我有以下代码... 我试图了解lock(TargetObject)的目的是什么? 当我们在执行命令时使用事务时,为什么要使用该锁定机制?
1回复

ado.net实体中的手动对象映射

我使用ado.net实体编写数据访问层。 但是我想手动完成(而不是通过工具生成代码)。 我需要帮助,该如何做,需要多少步骤和示例。
1回复

ADO.Net-将表char列映射到枚举

在现有的SQL表中, nvarchar列包含枚举信息。 我现在尝试使用一个枚举类来使用ADO.Net Entity Framework映射此列。 但是这似乎不可能,因为它需要整数列。 ADO EF是否不支持映射到char列的枚举,或者如何实现允许在查询时使用linq或lambda语
3回复

默认情况下,ADO.NET中映射到哪些SQL Server数据类型?

我需要所有SQL类型及其等效的.NET的列表。
5回复

c#ado.net:将数据库字段映射到属性的最佳方法

使用VS2005,.net 2.0和C# 大家好, 将存储的proc列映射到c#对象属性而不创建紧密耦合的最佳方法是什么。 例如,我不喜欢执行以下操作 因此,当存储的proc中的列更改为colxyz时,二进制代码将中断。 解决此问题的最佳做法是什么。 代码示例会有所
1回复

ado.net实体框架进行正向映射

我最近正在试验实体框架, 我想知道是否可以从头开始在设计器视图中为实体建模,然后让框架自动处理架构创建,外键等?