Excel 데이터베이스 가져오기 중 발생한 문제

6465 단어
이번 excel은 이전과 달리 먼저 excel의 중국어 이름에 따라 데이터 테이블의 열 속성에 대한 설명 속성을 찾고, 만약에 계속 있으면 excel의 열이 데이터 테이블의 열에 대응한다.그 다음에 excel의 첫 번째 줄은 비고줄이고 두 번째 줄은 열명이며 뒤에 데이터 줄이다.
이렇게 처리하는 장점은 앞으로 고객이 excel 템플릿을 바꾸고 가져온 정보를 바꾸며 시스템은 코드를 변경할 필요가 없고 비교적 유연하다는 것이다.
첫 번째 단계:
데이터베이스에서 데이터 테이블 이름과 설명 속성의 상관 관계를 찾습니다.
private DataTable dtNameMapping;
        public DataTable DtNameMapping
        {
            get
            {
                if (dtNameMapping == null)
                {
                    dtNameMapping = new DataTable();
                    if (!string.IsNullOrEmpty(tableName))
                    {    // fn_listextendedproperty 
                        string sql = string.Format(@"SELECT cast(objname as varchar(64)) objname ,cast(value as varchar(64)) value
                               FROM ::fn_listextendedproperty (NULL, 'user', 'dbo', 'table', '{0}', 'column', default)", tableName);
                        dtNameMapping = KPMSDatabase.KPMSDB.ExecuteDataSet(CommandType.Text, sql).Tables[0];
                    }
                }
                return dtNameMapping;
            }
        }

 
2단계:
데이터 조작에 편리하도록 excel을 DataTable에 읽기;
/// <summary>
        ///  Excel 
        /// </summary>
        /// <param name="fudExcel"> id</param>
        /// <param name="sheetName"> </param>
        /// <returns></returns>
        public DataTable GetExcelDataTable(FileUpload fudExcel, string sheetName)
        {
            DataTable dt = new DataTable();
            string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fudExcel.PostedFile.FileName + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; ;
            OleDbConnection Conn = new OleDbConnection(strConn);
            string sheet = "[" + sheetName + "$]";
            string strCom = string.Format("SELECT * FROM {0} WHERE 1=1 ", sheet);
            if (!string.IsNullOrEmpty(ExcelRow))
            {
                strCom += ExcelRow;
            }
            try
            {
                Conn.Open();
                OleDbDataAdapter comm = new OleDbDataAdapter(strCom, Conn);
                comm.Fill(dt);
                Conn.Close();
                dt = IgnoreExcelRowA(dt);

            }
            catch (Exception ex)
            {
                Conn.Close();
                //throw new Exception("Excel ");
                throw ex;
            }
            return dt;
        }

/// <summary>         /// , ,         /// </summary>         /// <param name="DtExcel"></param>         /// <returns></returns>         private DataTable IgnoreExcelRowA(DataTable DtExcel)         {

            if (DtExcel.Columns[0].ColumnName.IndexOf(" ") >= 0)             {

                if (DtExcel.Rows.Count > 0)                 {                     DataRow dr = DtExcel.Rows[0];

                    for (int n = 0; n < DtExcel.Columns.Count; n++)                     {                         if (!string.IsNullOrEmpty(dr[n].ToString()))                         {                             DtExcel.Columns[n].ColumnName = dr[n].ToString().Trim().Replace("'","");                         }                     }                     DtExcel.Rows.RemoveAt(0);                     DtExcel.AcceptChanges();                 }             }

            return DtExcel;         }


3단계:
excel 테이블의 열 이름에 따라 데이터베이스를 비교하여 해당하는 필드 이름을 찾습니다.
 /// <summary>
        ///  Excel , excel , excel 
        /// </summary>
        /// <param name="DataTable"> </param>
        /// <param name="dtExcel">excel </param>
        /// <returns></returns>
        public DataTable ExcelCompareSQL(DataTable dtNameMapping, DataTable dtExcel)
        {
            bool isContain = true;
            foreach (DataColumn dc in dtExcel.Columns)
            {
                DataRow[] drName = dtNameMapping.Select(string.Format("value='{0}'", dc.ColumnName.Trim().Replace("'","")));
                if (drName.Length == 1)
                {
                    dc.ColumnName = drName[0]["objname"].ToString();
                    dtExcel.AcceptChanges();
                }
                else
                {
                    isContain = false;
                    break;
                }
            }
            if (!isContain)
            {
                throw new Exception("Excel 。");
            }
            return dtExcel;
        }

문제: 이 단계에서 문제가 발생할 수 있습니다.
DataRow[] drName = dtNameMapping.Select(string.Format("value='{0}'", dc.ColumnName.Trim().Replace("'","")));
해당 테이블 DtNameMapping을 가져올 때 데이터 필드를 형식 변환하지 않고 직접 쓰는 경우
SELECT objname , value
FROM ::fn_listextendedproperty (NULL, 'user', 'dbo', 'table', 'ProjectEntity', 'column', default)


왜냐하면value의 데이터 형식은 sql_variant, 그래서 코드에서 dt를 사용합니다.select('value='{0}')는 작용하지 않습니다. 심지어 추적할 때 dt의value를 감시하는 것도 선택할 수 없습니다. 읽는 권한만 있고 삭제 수정 권한이 없습니다. 형식을 바꾸면 이 문제를 해결할 수 있습니다.
 
참고:
필드의 확장 속성을 수정하거나 추가하는 방법
EXEC sp_updateextendedproperty 'MS_Description',N' ','user',dbo,'table','ProjectEntity','column','CustomerName'

EXEC sp_addextendedproperty 'MS_Description',N' ','user',dbo,'table','ProjectEntity','column','Memo'

좋은 웹페이지 즐겨찾기