System.Data.ProviderBase.SchemaMapping.SetupSchemaWithKeyInfo C# (CSharp) Метод

SetupSchemaWithKeyInfo() приватный Метод

private SetupSchemaWithKeyInfo ( MissingMappingAction mappingAction, MissingSchemaAction schemaAction, bool gettingData, DataColumn parentChapterColumn, object chapterValue ) : object[]
mappingAction MissingMappingAction
schemaAction MissingSchemaAction
gettingData bool
parentChapterColumn DataColumn
chapterValue object
Результат object[]
        private object[] SetupSchemaWithKeyInfo(MissingMappingAction mappingAction, MissingSchemaAction schemaAction, bool gettingData, DataColumn parentChapterColumn, object chapterValue)
        {
            // must sort rows from schema table by ordinal because Jet is sorted by coumn name
            DbSchemaRow[] schemaRows = DbSchemaRow.GetSortedSchemaRows(_schemaTable, _dataReader.ReturnProviderSpecificTypes);
            Debug.Assert(null != schemaRows, "SchemaSetup - null DbSchemaRow[]");
            Debug.Assert(_dataReader.FieldCount <= schemaRows.Length, "unexpected fewer rows in Schema than FieldCount");

            if (0 == schemaRows.Length)
            {
                _dataTable = null;
                return null;
            }

            // Everett behavior, always add a primary key if a primary key didn't exist before
            // Whidbey behavior, same as Everett unless using LoadOption then add primary key only if no columns previously existed
            bool addPrimaryKeys = (((0 == _dataTable.PrimaryKey.Length) && ((4 <= (int)_loadOption) || (0 == _dataTable.Rows.Count)))
                                    || (0 == _dataTable.Columns.Count));

            DataColumn[] keys = null;
            int keyCount = 0;
            bool isPrimary = true; // assume key info (if any) is about a primary key

            string keyBaseTable = null;
            string commonBaseTable = null;

            bool keyFromMultiTable = false;
            bool commonFromMultiTable = false;

            int[] columnIndexMap = null;
            bool[] chapterIndexMap = null;

            int mappingCount = 0;

            object[] dataValues = null;
            List<object> addedItems = null;
            DataColumnCollection columnCollection = _dataTable.Columns;
            try
            {
                for (int sortedIndex = 0; sortedIndex < schemaRows.Length; ++sortedIndex)
                {
                    DbSchemaRow schemaRow = schemaRows[sortedIndex];

                    int unsortedIndex = schemaRow.UnsortedIndex;

                    bool ischapter = false;
                    Type fieldType = schemaRow.DataType;
                    if (null == fieldType)
                    {
                        fieldType = _dataReader.GetFieldType(sortedIndex);
                    }
                    if (null == fieldType)
                    {
                        throw ADP.MissingDataReaderFieldType(sortedIndex);
                    }

                    // if IDataReader, hierarchy exists and we will use an Int32,AutoIncrementColumn in this table
                    if (typeof(IDataReader).IsAssignableFrom(fieldType))
                    {
                        if (null == chapterIndexMap)
                        {
                            chapterIndexMap = new bool[schemaRows.Length];
                        }
                        chapterIndexMap[unsortedIndex] = ischapter = true;
                        fieldType = typeof(int);
                    }
                    else if (typeof(System.Data.SqlTypes.SqlXml).IsAssignableFrom(fieldType))
                    {
                        if (null == _xmlMap)
                        {
                            _xmlMap = new int[schemaRows.Length];
                        }
                        _xmlMap[sortedIndex] = SqlXml;
                    }
                    else if (typeof(System.Xml.XmlReader).IsAssignableFrom(fieldType))
                    {
                        fieldType = typeof(string);
                        if (null == _xmlMap)
                        {
                            _xmlMap = new int[schemaRows.Length];
                        }
                        _xmlMap[sortedIndex] = XmlDocument;
                    }

                    DataColumn dataColumn = null;
                    if (!schemaRow.IsHidden)
                    {
                        dataColumn = _tableMapping.GetDataColumn(_fieldNames[sortedIndex], fieldType, _dataTable, mappingAction, schemaAction);
                    }

                    string basetable = /*schemaRow.BaseServerName+schemaRow.BaseCatalogName+schemaRow.BaseSchemaName+*/ schemaRow.BaseTableName;
                    if (null == dataColumn)
                    {
                        if (null == columnIndexMap)
                        {
                            columnIndexMap = CreateIndexMap(schemaRows.Length, unsortedIndex);
                        }
                        columnIndexMap[unsortedIndex] = -1;

                        // if the column is not mapped and it is a key, then don't add any key information
                        if (schemaRow.IsKey)
                        {
#if DEBUG
                            if (AdapterSwitches.DataSchema.TraceVerbose)
                            {
                                Debug.WriteLine("SetupSchema: partial primary key detected");
                            }
#endif
                            // if the hidden key comes from a different table - don't throw away the primary key
                            // example SELECT [T2].[ID], [T2].[ProdID], [T2].[VendorName] FROM [Vendor] AS [T2], [Prod] AS [T1] WHERE (([T1].[ProdID] = [T2].[ProdID]))
                            if (keyFromMultiTable || (schemaRow.BaseTableName == keyBaseTable))
                            {
                                addPrimaryKeys = false; // don't add any future keys now
                                keys = null; // get rid of any keys we've seen
                            }
                        }
                        continue; // null means ignore (mapped to nothing)
                    }
                    else if ((null != _xmlMap) && (0 != _xmlMap[sortedIndex]))
                    {
                        if (typeof(System.Data.SqlTypes.SqlXml) == dataColumn.DataType)
                        {
                            _xmlMap[sortedIndex] = SqlXml;
                        }
                        else if (typeof(System.Xml.XmlDocument) == dataColumn.DataType)
                        {
                            _xmlMap[sortedIndex] = XmlDocument;
                        }
                        else
                        {
                            _xmlMap[sortedIndex] = 0; // datacolumn is not a specific Xml dataType, i.e. string

                            int total = 0;
                            for (int x = 0; x < _xmlMap.Length; ++x)
                            {
                                total += _xmlMap[x];
                            }
                            if (0 == total)
                            { // not mapping to a specific Xml datatype, get rid of the map
                                _xmlMap = null;
                            }
                        }
                    }

                    if (schemaRow.IsKey)
                    {
                        if (basetable != keyBaseTable)
                        {
                            if (null == keyBaseTable)
                            {
                                keyBaseTable = basetable;
                            }
                            else keyFromMultiTable = true;
                        }
                    }

                    if (ischapter)
                    {
                        if (null == dataColumn.Table)
                        {
                            dataColumn.AllowDBNull = false;
                            dataColumn.AutoIncrement = true;
                            dataColumn.ReadOnly = true;
                        }
                        else if (!dataColumn.AutoIncrement)
                        {
                            throw ADP.FillChapterAutoIncrement();
                        }
                    }
                    else
                    {
                        if (!commonFromMultiTable)
                        {
                            if ((basetable != commonBaseTable) && (!string.IsNullOrEmpty(basetable)))
                            {
                                if (null == commonBaseTable)
                                {
                                    commonBaseTable = basetable;
                                }
                                else
                                {
                                    commonFromMultiTable = true;
                                }
                            }
                        }
                        if (4 <= (int)_loadOption)
                        {
                            if (schemaRow.IsAutoIncrement && DataColumn.IsAutoIncrementType(fieldType))
                            {
                                // CONSIDER: use T-SQL "IDENT_INCR('table_or_view')" and "IDENT_SEED('table_or_view')"
                                //           functions to obtain the actual increment and seed values
                                dataColumn.AutoIncrement = true;

                                if (!schemaRow.AllowDBNull)
                                {
                                    dataColumn.AllowDBNull = false;
                                }
                            }

                            // setup maxLength, only for string columns since this is all the DataSet supports
                            if (fieldType == typeof(string))
                            {
                                // schemaRow.Size is count of characters for string columns, count of bytes otherwise
                                dataColumn.MaxLength = schemaRow.Size > 0 ? schemaRow.Size : -1;
                            }

                            if (schemaRow.IsReadOnly)
                            {
                                dataColumn.ReadOnly = true;
                            }
                            if (!schemaRow.AllowDBNull && (!schemaRow.IsReadOnly || schemaRow.IsKey))
                            {
                                dataColumn.AllowDBNull = false;
                            }

                            if (schemaRow.IsUnique && !schemaRow.IsKey && !fieldType.IsArray)
                            {
                                // note, arrays are not comparable so only mark non-arrays as unique, ie timestamp columns
                                // are unique, but not comparable
                                dataColumn.Unique = true;

                                if (!schemaRow.AllowDBNull)
                                {
                                    dataColumn.AllowDBNull = false;
                                }
                            }
                        }
                        else if (null == dataColumn.Table)
                        {
                            dataColumn.AutoIncrement = schemaRow.IsAutoIncrement;
                            dataColumn.AllowDBNull = schemaRow.AllowDBNull;
                            dataColumn.ReadOnly = schemaRow.IsReadOnly;
                            dataColumn.Unique = schemaRow.IsUnique;

                            if (fieldType == typeof(string) || (fieldType == typeof(SqlTypes.SqlString)))
                            {
                                // schemaRow.Size is count of characters for string columns, count of bytes otherwise
                                dataColumn.MaxLength = schemaRow.Size;
                            }
                        }
                    }
                    if (null == dataColumn.Table)
                    {
                        if (4 > (int)_loadOption)
                        {
                            AddAdditionalProperties(dataColumn, schemaRow.DataRow);
                        }
                        AddItemToAllowRollback(ref addedItems, dataColumn);
                        columnCollection.Add(dataColumn);
                    }

                    // The server sends us one key per table according to these rules.
                    //
                    // 1. If the table has a primary key, the server sends us this key.
                    // 2. If the table has a primary key and a unique key, it sends us the primary key
                    // 3. if the table has no primary key but has a unique key, it sends us the unique key
                    //
                    // In case 3, we will promote a unique key to a primary key IFF all the columns that compose
                    // that key are not nullable since no columns in a primary key can be null.  If one or more
                    // of the keys is nullable, then we will add a unique constraint.
                    //
                    if (addPrimaryKeys && schemaRow.IsKey)
                    {
                        if (keys == null)
                        {
                            keys = new DataColumn[schemaRows.Length];
                        }
                        keys[keyCount++] = dataColumn;
#if DEBUG
                        if (AdapterSwitches.DataSchema.TraceVerbose)
                        {
                            Debug.WriteLine("SetupSchema: building list of " + ((isPrimary) ? "PrimaryKey" : "UniqueConstraint"));
                        }
#endif
                        // see case 3 above, we do want dataColumn.AllowDBNull not schemaRow.AllowDBNull
                        // otherwise adding PrimaryKey will change AllowDBNull to false
                        if (isPrimary && dataColumn.AllowDBNull)
                        {
#if DEBUG
                            if (AdapterSwitches.DataSchema.TraceVerbose)
                            {
                                Debug.WriteLine("SetupSchema: changing PrimaryKey into UniqueContraint");
                            }
#endif
                            isPrimary = false;
                        }
                    }

                    if (null != columnIndexMap)
                    {
                        columnIndexMap[unsortedIndex] = dataColumn.Ordinal;
                    }
                    else if (unsortedIndex != dataColumn.Ordinal)
                    {
                        columnIndexMap = CreateIndexMap(schemaRows.Length, unsortedIndex);
                        columnIndexMap[unsortedIndex] = dataColumn.Ordinal;
                    }
                    mappingCount++;
                }

                bool addDataRelation = false;
                DataColumn chapterColumn = null;
                if (null != chapterValue)
                { // add the extra column in the child table
                    Type fieldType = chapterValue.GetType();
                    chapterColumn = _tableMapping.GetDataColumn(_tableMapping.SourceTable, fieldType, _dataTable, mappingAction, schemaAction);
                    if (null != chapterColumn)
                    {
                        if (null == chapterColumn.Table)
                        {
                            chapterColumn.ReadOnly = true;
                            chapterColumn.AllowDBNull = false;

                            AddItemToAllowRollback(ref addedItems, chapterColumn);
                            columnCollection.Add(chapterColumn);
                            addDataRelation = (null != parentChapterColumn);
                        }
                        mappingCount++;
                    }
                }

                if (0 < mappingCount)
                {
                    if ((null != _dataSet) && null == _dataTable.DataSet)
                    {
                        AddItemToAllowRollback(ref addedItems, _dataTable);
                        _dataSet.Tables.Add(_dataTable);
                    }
                    // setup the key
                    if (addPrimaryKeys && (null != keys))
                    {
                        if (keyCount < keys.Length)
                        {
                            keys = ResizeColumnArray(keys, keyCount);
                        }

                        if (isPrimary)
                        {
#if DEBUG
                            if (AdapterSwitches.DataSchema.TraceVerbose)
                            {
                                Debug.WriteLine("SetupSchema: set_PrimaryKey");
                            }
#endif
                            _dataTable.PrimaryKey = keys;
                        }
                        else
                        {
                            UniqueConstraint unique = new UniqueConstraint("", keys);
                            ConstraintCollection constraints = _dataTable.Constraints;
                            int constraintCount = constraints.Count;
                            for (int i = 0; i < constraintCount; ++i)
                            {
                                if (unique.Equals(constraints[i]))
                                {
#if DEBUG
                                    if (AdapterSwitches.DataSchema.TraceVerbose)
                                    {
                                        Debug.WriteLine("SetupSchema: duplicate Contraint detected");
                                    }
#endif
                                    unique = null;
                                    break;
                                }
                            }
                            if (null != unique)
                            {
#if DEBUG
                                if (AdapterSwitches.DataSchema.TraceVerbose)
                                {
                                    Debug.WriteLine("SetupSchema: adding new UniqueConstraint");
                                }
#endif
                                constraints.Add(unique);
                            }
                        }
                    }
                    if (!commonFromMultiTable && !string.IsNullOrEmpty(commonBaseTable) && string.IsNullOrEmpty(_dataTable.TableName))
                    {
                        _dataTable.TableName = commonBaseTable;
                    }
                    if (gettingData)
                    {
                        _indexMap = columnIndexMap;
                        _chapterMap = chapterIndexMap;
                        dataValues = SetupMapping(schemaRows.Length, columnCollection, chapterColumn, chapterValue);
                    }
                    else
                    {
                        // debug only, but for retail debug ability
                        _mappedMode = -1;
                    }
                }
                else
                {
                    _dataTable = null;
                }
                if (addDataRelation)
                {
                    AddRelation(parentChapterColumn, chapterColumn);
                }
            }
            catch (Exception e) when (ADP.IsCatchableOrSecurityExceptionType(e))
            {
                RollbackAddedItems(addedItems);
                throw;
            }
            return dataValues;
        }