문제

독자 데이터를 내 도메인 개체에 덤프하는 데 필요한 일반적인 지루한 "왼쪽/오른쪽" 코딩을 수행하는 "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
도움이 되었습니까?

해결책

Connection.GetSchema("Tables")는 데이터베이스의 테이블에 대한 메타 데이터를 반환하지만 사용자 정의 열을 정의하는 경우 sproc의 모든 내용을 반환하지는 않습니다.

예를 들어 *SELECT ProductName,'Testing' As ProductTestName FROM dbo.Products"와 같은 임의의 임시 열을 입력하는 경우 'ProductTestName'은 제품 테이블의 스키마에 없기 때문에 열로 표시되지 않습니다.이 문제를 해결하고 반환된 데이터에서 사용 가능한 모든 열을 요청하려면 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

솔직히 말해서 이것은 해킹입니다. ~해야 한다 모든 열을 반환하여 개체를 올바르게 수화하십시오.그러나 테이블 스키마에 정의되지 않은 경우에도 실제로 모든 열을 가져오는 이 판독기 메서드를 포함하려고 생각했습니다.

관계형 데이터를 도메인 모델에 매핑하는 이 접근 방식은 지연 로딩 시나리오에 들어갈 때 몇 가지 문제를 일으킬 수 있습니다.

다른 팁

이것도 확인해 보세요 내가 작성한 확장 방법 데이터 명령에 사용:

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을 많이 수행하는 경우 매우 편리할 수 있습니다.

각 sproc가 null, -1 또는 데이터가 없는 허용 가능한 값을 사용하여 전체 열 집합을 반환하도록 하면 어떨까요?IndexOutOfRangeException을 포착하거나 LinqToSql의 모든 내용을 다시 작성할 필요가 없습니다.

사용 GetSchemaTable() 메타데이터를 검색하는 메소드 DataReader.그만큼 DataTable 반환된 값을 사용하여 특정 열이 있는지 여부를 확인할 수 있습니다.

LinqToSql을 사용하면 어떨까요? 필요한 모든 것이 자동으로 수행됩니다.일반화를 위해 다른 것을 사용해도 됩니다. ORM 도구 .NET용

ORM을 사용하고 싶지 않다면 다음과 같은 경우에 리플렉션을 사용할 수도 있습니다(이 경우 ProductID의 이름이 양쪽에서 동일하지 않기 때문에 여기에 설명된 단순한 방식으로는 이를 수행할 수 없습니다).C#의 목록 공급자

나는 전화할 것이다 reader.GetOrdinal while 루프를 시작하기 전에 각 필드 이름에 대해.안타깝게도 GetOrdinal 던진다 IndexOutOfRangeException 필드가 존재하지 않으면 성능이 그다지 좋지 않습니다.

아마도 결과를 Dictionary<string, int> 그리고 그것을 사용 ContainsKey 필드가 제공되었는지 확인하는 방법입니다.

나는 결국 내 자신의 것을 작성하게 되었지만 이 매퍼는 꽤 훌륭하고 간단합니다: https://code.google.com/p/dapper-dot-net/

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top