다음을 통해 공유


데이터 바인딩(LINQ to SQL)

LINQ to SQL에서는 표 컨트롤과 같은 공용 컨트롤에 대한 바인딩을 지원합니다.특히 LINQ to SQL에서는 데이터 표에 바인딩과 마스터-세부 사항 바인딩 처리를 위한 기본 패턴을 표시 및 업데이트 측면 모두에서 정의합니다.

기본 원칙

LINQ to SQL에서는 LINQ 쿼리를 데이터베이스에서 실행하기 위해 SQL로 변환합니다.그 결과 강력한 형식의 IEnumerable이 생성됩니다.이러한 개체는 일반적인 CLR(공용 언어 런타임) 개체이므로 일반 개체 데이터 바인딩을 사용하여 결과를 표시할 수 있습니다.반면 변경 작업(삽입, 업데이트 및 삭제)에는 추가 단계가 필요합니다.

작업

Windows Forms 컨트롤에 명시적으로 바인딩하려면 IListSource를 구현합니다.데이터 소스 제네릭 Table<TEntity>(C#의 Table<T> 또는 Visual Basic의 Table(Of T)) 및 제네릭 DataQueryIListSource를 구현하도록 업데이트되었습니다. UI(사용자 인터페이스) 데이터 바인딩 엔진(Windows Forms 및 Windows Presentation Foundation)에서는 모두 해당 데이터 소스에서 IListSource를 구현하는지 여부를 테스트합니다.따라서 다음 예제와 같이 쿼리의 직접 영향을 컨트롤의 데이터 소스에 쓰면 LINQ to SQL 컬렉션 생성이 암시적으로 호출됩니다.

Dim dataGrid1 As New DataGrid()
Dim dataGrid2 As New DataGrid()
Dim dataGrid3 As New DataGrid()

Dim custQuery = _
    From cust In db.Customers _
    Select cust

dataGrid1.DataSource = custQuery
dataGrid2.DataSource = custQuery
dataGrid2.DataMember = "Orders"

Dim bs = _
    New BindingSource()
bs.DataSource = custQuery
dataGrid3.DataSource = bs
DataGrid dataGrid1 = new DataGrid();
DataGrid dataGrid2 = new DataGrid();
DataGrid dataGrid3 = new DataGrid();

var custQuery =
    from cust in db.Customers
    select cust;
dataGrid1.DataSource = custQuery;
dataGrid2.DataSource = custQuery;
dataGrid2.DataMember = "Orders";

BindingSource bs = new BindingSource();
bs.DataSource = custQuery;
dataGrid3.DataSource = bs;

Windows Presentation Foundation에서도 동일한 동작이 발생합니다.

Dim listView1 As New ListView()
Dim custQuery2 = _
From cust In db.Customers _
Select cust

Dim ItemsSource As New ListViewItem
ItemsSource = custQuery2
ListView listView1 = new ListView();
var custQuery2 =
    from cust in db.Customers
    select cust;

ListViewItem ItemsSource = new ListViewItem();
ItemsSource = (ListViewItem)custQuery2;

컬렉션 생성은 GetList에서 제네릭 Table<TEntity> 및 제네릭 DataQuery에 의해 구현됩니다.

IListSource 구현

LINQ to SQL에서는 다음과 같은 두 위치에서 IListSource를 구현합니다.

  • 데이터 소스가 Table<TEntity>인 경우 LINQ to SQL에서는 테이블을 탐색하여 테이블의 참조를 보관하는 DataBindingList 컬렉션을 채웁니다.

  • 데이터 소스가 IQueryable<T>인 경우다음과 같은 두 가지 시나리오가 있습니다.

    • LINQ to SQL가 IQueryable<T>에서 기본 Table<TEntity>을 찾는 경우 소스를 편집할 수 있으며 첫 번째 글머리 기호의 경우와 상황이 같아집니다.

    • LINQ to SQL에서 기본 Table<TEntity>을 찾을 수 없는 경우 소스를 편집할 수 없습니다(예: groupby). LINQ to SQL에서는 쿼리를 검색하여 지정된 속성의 T 엔터티에 대한 정렬 기능을 구현하는 단순 BindingList<T>인 제네릭 SortableBindingList를 채웁니다.

특수 컬렉션

이 문서의 앞부분에서 설명한 많은 기능에서 BindingList<T>는 몇 가지 다른 클래스용으로 설계된 특수 클래스입니다.이러한 클래스는 제네릭 SortableBindingList 및 제네릭 DataBindingList 클래스입니다.둘 다 정수로 선언됩니다.

제네릭 SortableBindingList

이 클래스는 BindingList<T>에서 상속되며 BindingList<T>의 정렬 가능한 버전입니다.정렬은 메모리 내 솔루션이며 데이터베이스 자체와는 연결하지 않습니다.BindingList<T>IBindingList를 구현하지만 기본적으로 정렬을 지원하지 않습니다.그러나 BindingList<T>는 가상 코어 메서드를 사용하여 IBindingList를 구현합니다.이러한 메서드는 쉽게 재정의할 수 있습니다.제네릭 SortableBindingListSupportsSortingCore, SortPropertyCore, SortDirectionCoreApplySortCore를 재정의합니다.ApplySortCoreApplySort에서 호출되며 지정한 속성의 T 항목 목록을 정렬합니다.

속성이 T에 속하지 않으면 예외가 발생합니다.

정렬을 수행하기 위해 LINQ to SQL에서는 제네릭 IComparer.Compare에서 상속되는 제네릭 SortableBindingList.PropertyComparer 클래스를 만들고 지정된 형식 T에 대한 기본 비교자인 PropertyDescriptor와 방향을 구현합니다.이 클래스는 T가 PropertyDescriptorPropertyType인 경우 T의 Comparer를 동적으로 만듭니다.그런 다음 정적 제네릭 Comparer에서 기본 비교자를 검색합니다.기본 인스턴스는 리플렉션을 사용하여 가져옵니다.

제네릭 SortableBindingListDataBindingList의 기본 클래스입니다.제네릭 SortableBindingList에서는 항목 추가/제거 추적을 일시 중단 또는 다시 시작하기 위한 두 개의 가상 메서드를 제공합니다.이러한 두 메서드는 정렬과 같은 기본 기능에 사용할 수 있지만 실제로 제네릭 DataBindingList와 같은 상위 클래스에서 구현됩니다.

제네릭 DataBindingList

이 클래스는 제네릭 SortableBindingLIst에서 상속됩니다.제네릭 DataBindingList는 컬렉션의 초기 채우기에 사용되는 제네릭 IQueryable에 대한 기본 제네릭 Table의 참조를 보관합니다.제네릭 DatabindingListInsertItem() 및 RemoveItem()를 재정의하여 항목 추가/제거에 대한 추적을 컬렉션에 추가합니다.또한 추적 기능의 추상 일시 중단/다시 시작을 구현하여 추적을 조건부로 만듭니다.이 기능을 사용하면 제네릭 DataBindingList에서 부모 클래스의 추적 기능에 대한 모든 다형적 사용을 활용할 수 있습니다.

EntitySet에 바인딩

EntitySet은 이미 IBindingList를 구현하는 컬렉션이므로 EntitySet에 바인딩하는 것은 특수한 경우입니다.LINQ to SQL에서는 정렬 및 취소(ICancelAddNew) 지원을 추가합니다.EntitySet 클래스는 내부 목록을 사용하여 엔터티를 저장합니다.이 목록은 제네릭 배열을 기반으로 하는 하위 수준 컬렉션인 제네릭 ItemList 클래스입니다.

정렬 기능 추가

배열에서는 T의 Comparer와 함께 사용할 수 있는 정렬 메서드(Array.Sort())를 제공합니다.LINQ to SQL에서는 이 항목의 앞부분에서 설명한 제네릭 SortableBindingList.PropertyComparer 클래스를 사용하여 이 Comparer에서 정렬할 속성과 방향을 가져옵니다.ApplySort 메서드를 제네릭 ItemList에 추가하면 이 기능이 호출됩니다.

이제 다음과 같이 EntitySet측에서 정렬 지원을 선언해야 합니다.

System.Windows.Forms.BindingSource를 사용하고 EntitySet<TEntity>을 System.Windows.Forms.BindingSource.DataSource에 바인딩하는 경우 EntitySet<Tentity>.GetNewBindingList를 호출하여 BindingSource.List를 업데이트해야 합니다.

System.Windows.Forms.BindingSource를 사용하고 BindingSource.DataMember 속성을 설정하는 경우, EntitySet<TEntity>을 노출하는 BindingSource.DataMember에 명명된 속성이 포함된 클래스를 BindingSource.DataSource로 설정하면 EntitySet<Tentity>.GetNewBindingList를 호출하여 BindingSource.List를 업데이트할 필요가 없지만 정렬 기능을 사용할 수 없게 됩니다.

캐싱

LINQ to SQL 쿼리는 GetList를 구현합니다.Windows Forms BindingSource 클래스는 이 인터페이스를 검색하는 경우 단일 연결에 대해 GetList()를 세 번 호출합니다.이 문제를 해결하기 위해 LINQ to SQL에서는 저장한 인스턴스당 캐시 하나를 구현하고 항상 동일하게 생성된 컬렉션을 반환합니다.

취소

IBindingList에서는 컨트롤이 바인딩된 컬렉션에서 새 항목을 만드는 데 사용하는 AddNew 메서드를 정의합니다.DataGridView 컨트롤은 표시된 마지막 행의 헤더에 별이 들어 있는 경우 이 기능을 아주 잘 보여 줍니다.별은 새 항목을 추가할 수 있다는 것을 나타냅니다.

또한 컬렉션에서는 이 기능 외에 ICancelAddNew를 구현합니다.이 기능을 사용하면 컨트롤에서 새로 편집한 항목을 취소하거나 항목이 유효한지 검사할 수 있습니다.

ICancelAddNew는 모든 LINQ to SQL 데이터 바인딩 컬렉션(제네릭 SortableBindingList 및 제네릭 EntitySet)에서 구현됩니다. 두 구현 모두에서 코드는 다음과 같이 수행됩니다.

  • 컬렉션에서 항목이 삽입된 다음 제거됩니다.

  • UI에서 편집을 커밋하지 않는 한 변경 내용을 추적하지 않습니다.

  • 편집을 취소(CancelNew)하지 않는 한 변경 내용을 추적하지 않습니다.

  • 편집이 커밋되면(EndNew) 추적을 허용합니다.

  • 새 항목을 AddNew에서 가져오지 않은 경우 컬렉션이 정상적으로 동작할 수 있습니다.

문제 해결

이 단원에서는 LINQ to SQL 데이터 바인딩 응용 프로그램의 문제를 해결하는 데 도움이 되는 몇 가지 항목을 설명합니다.

  • 속성을 사용해야 합니다. 필드만 사용하는 것으로는 충분하지 않습니다.Windows Forms에는 이러한 사용법이 필요합니다.

  • 기본적으로 image, varbinary 및 timestamp 데이터베이스 형식은 바이트 배열에 매핑됩니다.ToString()은 이 시나리오에서 지원되지 않으므로 이러한 개체를 표시할 수 없습니다.

  • 기본 키에 매핑된 클래스 멤버에는 setter가 있지만 LINQ to SQL에서는 개체 ID 변경이 지원되지 않습니다.따라서 매핑에서 사용된 기본/고유 키는 데이터베이스에서 업데이트할 수 없습니다.표를 변경하면 SubmitChanges를 호출할 때 예외가 발생합니다.

  • 엔터티가 두 개의 다른 표(예: 마스터와 세부 사항)에 바인딩되어 있으면 마스터 표의 Delete가 세부 사항 표로 전파되지 않습니다.

참고 항목

기타 리소스

배경 정보(LINQ to SQL)