2009-08-05 3 views
2

응용 프로그램 전체에 강력한 형식의 데이터 집합이 여러 개 있습니다. 각각의 테이블이 여러 개이기 때문에 데이터를 업데이트하는 메소드를 작성하는 것은 지루한 일입니다. 모든 테이블을 쉽게 업데이트 할 수있는 일반 함수를 만들고 싶습니다. 각 DataSet에 대해이 중 하나를 만들어야하더라도 상관 없지만 한 함수가 모든 데이터를 처리 할 수 ​​있다면 놀라운 것입니다!Reflection (C#)을 사용하여 일반 DataTable 및 TableAdaptor를 업데이트하십시오.

새 레코드, 업데이트 된 레코드 또는 삭제 된 레코드가 여러 개 있으며 각 행에 올바르게 플래그가 지정되어야합니다. 이 함수는 실제 저장을 처리해야합니다. 다음은 지금까지 내가 가지고있는 것입니다 :

다른 개발자가 다른 응용 프로그램에서 가지고있는 또 다른 코드에서이 코드를 적용했습니다. 지금까지 주요 차이점은 데이터 배열의 배열 (객체 유형)을 전달하고 foreach (oParamaterInfoArray의 ParameterInfo oPI) 블록 (여기에서 'myParamaterInfoArray')에있는 블록이 개별적으로 설정된 경우 세 개의 DataSets (전역으로 인스턴스화 됨) NameOfDataSet '은 데이터 집합 중 하나임)

누구나이 기능을 끝내는 방향으로 약간의 푸시 (또는 밀림?)를 줄 수 있습니까? 나는 내가 그곳에 있다는 것을 압니다. 그러나 나는 무언가를 보는 것 이상의 느낌입니다. 이 코드는 오류없이 컴파일됩니다.

+0

+1 저는 항상 xxTableAdapter 클래스가 공통 인터페이스를 구현했거나 기본 클래스에서 파생 된 것으로 생각했습니다. –

+0

xxTableAdapter는 SqlDataAdapter에서 가져온 것으로 생각하고 DbDataAdapter에서 상속받습니다. 또한 IDbDataAdapter 인터페이스를 구현해야합니다. –

답변

1

그냥 기본 클래스 인 DbDataAdapter, DataSet 및 DataTable로 처리 할 수 ​​없습니까?

DataSet.Tables [ "name"]을 (를) 수행하여 이름으로 테이블에 액세스 할 수 있습니다. 그러면 DbDataAdapters 업데이트 메서드에 전달할 수있는 DataTable 개체가 반환됩니다.

또는 TableAdapter가 DataSet의 모든 테이블을 업데이트하는 경우 전체 DataSet을 update 메서드에 직접 전달할 수 있습니다.

그렇다면 그렇게 할 기회가 있다면 유형이 지정된 데이터 세트를 다시 생각해 보시기 바랍니다. 내 경험에 비추어 볼 때 유지 관리 및 사용에 번거 로움이되며 일반 DataTable, DataSet 및 DbDataAdapter 클래스가 직접 사용하기가 훨씬 쉽습니다.

+0

나는 이것에 동의 할 의향이있다. 불행히도 나는 이것을 사용하는 것에 갇혀있는 것 같다. 그것은 나보다 위의 개발자가 사용하기를 원하는 방향입니다. 바로 SQL과 저장 프로 시저를 사용하는 것보다 낫습니다. 나는 도달 테이블 용 TableAdaptors를 가지고 있습니다. 어쩌면 각 데이터 집합의 모든 TableAdaptors를 반복하고 데이터 집합을 전달하는 방법을 찾아야합니다. 그것은 업데이트하는 방법을 알고 있으며 인생과 함께 나아갈 수있는 테이블을 업데이트 할 것입니까? – bdwakefield

+0

그것은 알고있는 테이블 만 업데이트해야하므로 모든 테이블 어댑터를 반복하고 데이터 세트를 update 메소드에 전달하는 것이 안전해야합니다. 비록 성능이 어떻게 될지 확신하지 못합니다. –

+0

다른 큰 문제는 제가 실행하고있는 부분입니다. dev는 데이터 셋을 사용하기 위해 내 애플리케이션을 업데이트하기를 원합니다. 데이터 집합을 사용하지 않는 다른 응용 프로그램과 너무 잘 작동하지 않습니다. 귀하의 의견을 보내 주셔서 감사합니다. 나는 그 접근 방식을 취하고 어떻게 일이 진행되는지 살펴볼 것입니다. – bdwakefield

0

DAL에서 반사 효과를 많이 사용 하시겠습니까? 아마도 LINQ to SQL이나 Hibernate와 같은 ORM이 좋은 대안일까요?

+0

이것은 .NET 2.0이며 우리가 함께 사용해야하는 것입니다. 아직 3.0 또는 3.5로 업그레이드 할 계획이 없습니다. 나는 ORM이나 NHibernate에 익숙하지 않다. 프로젝트에 프레임 워크를 추가하는 것이 좋은 아이디어라는 것을 나는 모른다. – bdwakefield

2

나는 이것을 사용 해왔다. 그것은 몇 가지 최적화가 필요합니다. 또한 데이터 집합의 관계에 따라 올바른 순서로 테이블을 업데이트합니다 (셀 참조가없는 경우 행을 정렬하여 처리 할 수 ​​있지만 간단하게하기 위해 여기에 게시하지 않습니다).

public static void Save(DataSet data, SqlConnection connection) 
    { 
     /// Dictionary for associating adapters to tables. 
     Dictionary<DataTable, SqlDataAdapter> adapters = new Dictionary<DataTable, SqlDataAdapter>(); 

     foreach (DataTable table in data.Tables) 
     { 
      /// Find the table adapter using Reflection. 
      Type adapterType = GetTableAdapterType(table); 
      SqlDataAdapter adapter = SetupTableAdapter(adapterType, connection, validityEnd); 
      adapters.Add(table, adapter); 
     } 

     /// Save the data. 
     Save(data, adapters); 
    } 

    static Type GetTableAdapterType(DataTable table) 
    { 
     /// Find the adapter type for the table using the namespace conventions generated by dataset code generator. 
     string nameSpace = table.GetType().Namespace; 
     string adapterTypeName = nameSpace + "." + table.DataSet.DataSetName + "TableAdapters." + table.TableName + "TableAdapter"; 
     Type adapterType = Type.GetType(adapterTypeName); 
     return adapterType; 
    } 

    static SqlDataAdapter SetupTableAdapter(Type adapterType, SqlConnection connection) 
    { 
     /// Set connection to TableAdapter and extract SqlDataAdapter (which is private anyway). 
     object adapterObj = Activator.CreateInstance(adapterType); 
     SqlDataAdapter sqlAdapter = (SqlDataAdapter)GetPropertyValue(adapterType, adapterObj, "Adapter"); 
     SetPropertyValue(adapterType, adapterObj, "Connection", connection); 

     return sqlAdapter; 
    } 

    static object GetPropertyValue(Type type, object instance, string propertyName) 
    { 
     return type.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance).GetValue(instance, null); 
    } 

    static void SetPropertyValue(Type type, object instance, string propertyName, object propertyValue) 
    { 
     type.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance).SetValue(instance, propertyValue, null); 
    } 

    static void Save(DataSet data, Dictionary<DataTable, SqlDataAdapter> adapters) 
    { 
     if (data == null) 
      throw new ArgumentNullException("data"); 

     if (adapters == null) 
      throw new ArgumentNullException("adapters"); 

     Dictionary<DataTable, bool> procesedTables = new Dictionary<DataTable, bool>(); 
     List<DataTable> sortedTables = new List<DataTable>(); 

     while (true) 
     { 
      DataTable rootTable = GetRootTable(data, procesedTables); 
      if (rootTable == null) 
       break; 

      sortedTables.Add(rootTable); 
     } 

     /// Updating Deleted rows in Child -> Parent order. 
     for (int i = sortedTables.Count - 1; i >= 0; i--) 
     { 
      Update(adapters, sortedTables[i], DataViewRowState.Deleted); 
     } 

     /// Updating Added/Modified rows in Parent -> Child order. 
     for (int i = 0; i < sortedTables.Count; i++) 
     { 
      Update(adapters, sortedTables[i], DataViewRowState.Added | DataViewRowState.ModifiedCurrent); 
     } 
    } 

    static void Update(Dictionary<DataTable, SqlDataAdapter> adapters, DataTable table, DataViewRowState states) 
    { 
     SqlDataAdapter adapter = null; 

     if (adapters.ContainsKey(table)) 
      adapter = adapters[table]; 

     if (adapter != null) 
     { 
      DataRow[] rowsToUpdate = table.Select("", "", states); 

      if (rowsToUpdate.Length > 0) 
       adapter.Update(rowsToUpdate); 
     } 
    } 

    static DataTable GetRootTable(DataSet data, Dictionary<DataTable, bool> procesedTables) 
    { 
     foreach (DataTable table in data.Tables) 
     { 
      if (!procesedTables.ContainsKey(table)) 
      { 
       if (IsRootTable(table, procesedTables)) 
       { 
        procesedTables.Add(table, false); 
        return table; 
       } 
      } 
     } 

     return null; 
    } 

    static bool IsRootTable(DataTable table, Dictionary<DataTable, bool> procesedTables) 
    { 
     foreach (DataRelation relation in table.ParentRelations) 
     { 
      DataTable parentTable = relation.ParentTable; 
      if (parentTable != table && !procesedTables.ContainsKey(parentTable)) 
       return false; 
     } 

     return true; 
    }