[GIS] Transfering a lot of features from geodatabases

arcobjectsenterprise-geodatabasefile-geodatabase

I'm having a problem where I need to export a large amount of content from 2 geodatabases of different nature (SDE -> File).

I have three options: Spatial Select, a regular SQL select and the full feature class/table.

What are the best practices to handle these large transfers?

I'm having issues with the following code:

    public void ExportAll(IGisEntity entity)
    {
        ITable table = _Context.GetEntityTable(entity.EntityName);
        IFeatureWorkspace workspace = _OutWorkspace as IFeatureWorkspace;
        ITable outTable = workspace.OpenTable(entity.EntityFeatureClass);

        if (table == null)
            throw new ArgumentException("A tabela de origem não existe.");

        if (outTable == null)
            throw new ArgumentException("A tabela de destino não existe.");

        ICursor selectCursor = table.Search(null, false);
        IRow selectRow = null;

        ICursor insertCursor = outTable.Insert(true);
        IRowBuffer buffer = outTable.CreateRowBuffer();

        int recordCount = table.RowCount(null);
        int count = 0;
        int step = recordCount;
        if (recordCount > 10000)
            step = Convert.ToInt32(Math.Round(recordCount * .1, 0));

        int remainder = 0;

        while ((selectRow = selectCursor.NextRow()) != null)
        {
            buffer = selectRow;
            insertCursor.InsertRow(buffer);
            count++;
            Math.DivRem(count, step, out remainder);
            if (remainder == 0)
                insertCursor.Flush();
        }
        insertCursor.Flush();

        CustomComReleaser.ReleaseComObject(insertCursor);
        CustomComReleaser.ReleaseComObject(selectCursor);
    }

    public void ExportSelect(IGisEntity entity, int sectorNo)
    {
        ITable table = _Context.GetEntityTable(entity.EntityName);
        IFeatureWorkspace outWork = _OutWorkspace as IFeatureWorkspace;
        ITable outTable = outWork.OpenTable(entity.EntityFeatureClass);

        if (table == null)
            throw new ArgumentException("A tabela de origem não existe.");

        if (outTable == null)
            throw new ArgumentException("A tabela de destino não existe.");

        IQueryFilter filter = new QueryFilterClass();
        filter.WhereClause = String.Format(@"{0}_GR_IDENTIFICADOR LIKE '1{1}%'", entity.EntityCode.Substring(1, 3), sectorNo.ToString());

        ICursor selectCursor = table.Search(filter, false);
        IRow selectRow = null;

        IRowBuffer buffer = outTable.CreateRowBuffer();
        ICursor insertCursor = outTable.Insert(true);

        int recordCount = table.RowCount(filter);
        int count = 0;
        int step = recordCount;
        if (recordCount > 10000)
            step = Convert.ToInt32(Math.Round(recordCount * .1,0));

        int remainder = 0;

        while ((selectRow = selectCursor.NextRow()) != null)
        {
            buffer = selectRow;
            insertCursor.InsertRow(buffer);
            count++;
            Math.DivRem(count, step, out remainder);
            if (remainder == 0)
                insertCursor.Flush();
        }
        insertCursor.Flush();

        CustomComReleaser.ReleaseComObject(insertCursor);
        CustomComReleaser.ReleaseComObject(selectCursor);
    }

When one operating on ArcSDE systems these methods tend to hang and gives me I/O errors.

I look into IGeodatabaseBridge interface and IGeoDbDataTransfer, but none of them gives me the option to export a cursor (product of a select, for example).

This is now a major issue: everytime I'm getting a RPC_ERROR_SERVERFAULT with this snippet.

        while ((row = select.NextRow()) != null)
        {
            buffer = row as IRowBuffer;
            insert.InsertRow(buffer);
            count++;
            if (count == 4999)
            {
                insert.Flush(); // this is where the error explodes at my face!
                count = 0;
            }
        }

Any choices?

Best Answer

You might try using one of the GP copy tools (Copy, Copy Rows, Copy Features). I've found some of esri's push toward more coarse-grained operations annoying, but I've also found that the GP tools can be more reliable in some situations than straight c# coding.

Obviously, one thing to watch for is the differing limitations placed on different geodatabase formats (e.g. file gdb fields can't always go directly into an SQL Server SDE because of the length limit on field names).