### Bulk Data Import

This is a simple example of using Soapi.CS for bulk data importation. 

This sample creates/updates a SQLite database with the the complete profile of all Stack Exchange users with reputation >= 100 and assigns a rank according to order of appearance.

Soapi processes the ~1000 requests required in less than 5 minutes.

You may run this code against the same database and the records are updated in place.

This code requires references to [System.Data.SQLite][1] and Soapi.dll.

Code very similar to this is the core of the [SO-REP][2] service.

**Usage:**

    new SoapiUserIndexer()
        .Index("data source=users.db;new=true", apikey);

**Code:**


    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SQLite;
    using System.Linq;
    using Soapi.Domain;
    
    namespace Soapi.Data
    {
    
        public class SoapiUserIndexer
        {
    
            /// <summary>
            /// 
            /// Provides you with a local database of all stack exchange users with 
            /// rep >=100, 90,000 records, in less than 5 minutes using Soapi.CS
            /// 
            /// It is not recommended to decrease the minimum rep value as the numbers
            /// increase drastically with questionable benefit.
            /// 
            /// This is the core of the SO-REP Service, which ranks provides 
            /// ranking data.
            /// 
            /// Requires System.Data.SQLite
            /// http://sqlite.phxsoftware.com/
            /// 
            /// </summary>
            /// <param name="connectionString"></param>
            /// <param name="apiKey"></param>
            public void Index(string connectionString, string apiKey)
            {
                var ctx = new ApiContext(apiKey).Initialize(false);
    
                var lastModified = DateTime.Now;
                const int batchSize = 50;
                const int minRep = 100;
    
                using (var connection = new SQLiteConnection(connectionString))
                {
                    connection.Open();
                    var cmd = connection.CreateCommand();
                    cmd.CommandText = CreateUsersTable;
                    cmd.ExecuteNonQuery();
    
    
                    foreach (Site site in ctx.Sites.Where(s => s.ApiEndpoint.IndexOf("stackauth") == -1))
                    {
    
                        // get the count of users with Rep >= 100 and div by 100 to get a page count
                        var pageCount = (int)(Math.Ceiling((double)site.Users.Min(minRep).Total / 100) + 1);
    
                        var batchCount = Math.Ceiling((double)pageCount / batchSize);
                        for (int i = 0; i < batchCount; i++)
                        {
                            var startPage = i*batchSize + 1;
                            var rank = (batchCount*i) + 1;
                            var users = site.Users.PageCount(batchSize).Page(startPage).Min(minRep).ToList();
    
                            using (var txn = connection.BeginTransaction())
                            {
                                cmd = BuildInsertCommand();
                                cmd.Connection = connection;
                                foreach (User item in users)
                                {
                                    cmd.Parameters["@ApiEndpoint"].Value = item.Site.ApiEndpoint;
                                    cmd.Parameters["@UserId"].Value = item.UserId;
                                    cmd.Parameters["@AssociationId"].Value = item.AssociationId;
                                    cmd.Parameters["@UserType"].Value = item.UserType.ToString();
                                    cmd.Parameters["@DisplayName"].Value = item.DisplayName ?? "";
                                    cmd.Parameters["@AboutMe"].Value = item.AboutMe ?? "";
                                    cmd.Parameters["@Location"].Value = item.Location ?? "";
                                    cmd.Parameters["@WebsiteUrl"].Value = item.WebsiteUrl ?? "";
                                    cmd.Parameters["@EmailHash"].Value = item.EmailHash ?? "";
                                    cmd.Parameters["@CreationDate"].Value = item.CreationDate;
                                    cmd.Parameters["@LastAccessDate"].Value = item.LastAccessDate;
                                    cmd.Parameters["@TimedPenaltyDate"].Value = item.TimedPenaltyDate;
                                    cmd.Parameters["@AcceptRate"].Value = item.AcceptRate;
                                    cmd.Parameters["@Age"].Value = item.Age;
                                    cmd.Parameters["@AnswerCount"].Value = item.AnswerCount;
                                    cmd.Parameters["@DownVoteCount"].Value = item.DownVoteCount;
                                    cmd.Parameters["@QuestionCount"].Value = item.QuestionCount;
                                    cmd.Parameters["@Reputation"].Value = item.Reputation;
                                    cmd.Parameters["@UpVoteCount"].Value = item.UpVoteCount;
                                    cmd.Parameters["@ViewCount"].Value = item.ViewCount;
                                    cmd.Parameters["@BadgesGold"].Value = item.BadgeCounts.Gold;
                                    cmd.Parameters["@BadgesSilver"].Value = item.BadgeCounts.Silver;
                                    cmd.Parameters["@BadgesBronze"].Value = item.BadgeCounts.Bronze;
                                    cmd.Parameters["@Rank"].Value = rank++;
                                    cmd.Parameters["@LastModifiedDate"].Value = lastModified;
                                    cmd.ExecuteNonQuery();
                                }
                                txn.Commit();
                            }
                        }
                    }
    
                    connection.Close();
                }
            }
    
            private static SQLiteCommand BuildInsertCommand()
            {
                var cmd = new SQLiteCommand(SqlUerInsertOrUpdate)
                    {
                        CommandText = SqlUerInsertOrUpdate
                    };
    
                foreach (var item in new List<object[]>
                    {
                        new object[]{"@ApiEndpoint", DbType.String,128},
                        new object[]{"@UserId", DbType.Int32},
                        new object[]{"@AssociationId", DbType.Guid},
                        new object[]{"@UserType", DbType.String,20},
                        new object[]{"@DisplayName", DbType.String,50},
                        new object[]{"@AboutMe", DbType.String,4000},
                        new object[]{"@Location", DbType.String,128},
                        new object[]{"@WebsiteUrl", DbType.String,256},
                        new object[]{"@EmailHash", DbType.String,64},
                        new object[]{"@CreationDate", DbType.DateTime},
                        new object[]{"@LastAccessDate", DbType.DateTime},
                        new object[]{"@TimedPenaltyDate", DbType.DateTime},
                        new object[]{"@AcceptRate", DbType.Int32},
                        new object[]{"@Age", DbType.Int32},
                        new object[]{"@AnswerCount", DbType.Int32},
                        new object[]{"@DownVoteCount", DbType.Int32},
                        new object[]{"@QuestionCount", DbType.Int32},
                        new object[]{"@Reputation", DbType.Int32},
                        new object[]{"@UpVoteCount", DbType.Int32},
                        new object[]{"@ViewCount", DbType.Int32},
                        new object[]{"@BadgesGold", DbType.Int32},
                        new object[]{"@BadgesSilver", DbType.Int32},
                        new object[]{"@BadgesBronze", DbType.Int32},
                        new object[]{"@Rank", DbType.Int32},
                        new object[]{"@LastModifiedDate",DbType.DateTime}
                    })
                {
                    var p = new SQLiteParameter { ParameterName = (string)item[0], DbType = (DbType)item[1] };
                    if (p.DbType == DbType.String)
                    {
                        p.Size = (int)item[2];
                    }
                    cmd.Parameters.Add(p);
                }
                return cmd;
            }
    
    
            private const string SqlUerInsertOrUpdate = @"
                   INSERT OR REPLACE INTO [Users] ([ApiEndpoint],[UserId],[AssociationId],[UserType],[DisplayName],[AboutMe],[Location]
                   ,[WebsiteUrl],[EmailHash],[CreationDate],[LastAccessDate],[TimedPenaltyDate],[AcceptRate],[Age],[AnswerCount],[DownVoteCount]
                   ,[QuestionCount],[Reputation],[UpVoteCount],[ViewCount],[BadgesGold],[BadgesSilver],[BadgesBronze],[Rank],[LastModifiedDate]) 
                   VALUES (@ApiEndpoint,@UserId,@AssociationId,@UserType,@DisplayName,@AboutMe,@Location,@WebsiteUrl,@EmailHash,@CreationDate
                   ,@LastAccessDate,@TimedPenaltyDate,@AcceptRate,@Age,@AnswerCount,@DownVoteCount,@QuestionCount,@Reputation,@UpVoteCount
                   ,@ViewCount,@BadgesGold,@BadgesSilver,@BadgesBronze,@Rank,@LastModifiedDate);";
    
            private const string CreateUsersTable = @"
                CREATE TABLE IF NOT EXISTS [Users] (
                    [RowId] integer PRIMARY KEY AUTOINCREMENT NOT NULL,
                    [ApiEndpoint] varchar(128) NOT NULL,
                    [UserId] int NOT NULL,
                    [AssociationId] guid NOT NULL,
                    [UserType] varchar(20) NOT NULL,
                    [DisplayName] nvarchar(50) NOT NULL,
                    [AboutMe] nvarchar(4000) NOT NULL,
                    [Location] nvarchar(128) NOT NULL,
                    [WebsiteUrl] nvarchar(256) NOT NULL,
                    [EmailHash] varchar(64) NOT NULL,
                    [CreationDate] datetime NOT NULL,
                    [LastAccessDate] datetime NOT NULL,
                    [TimedPenaltyDate] datetime NOT NULL,
                    [AcceptRate] int NOT NULL,
                    [Age] int NOT NULL,
                    [AnswerCount] int NOT NULL,
                    [DownVoteCount] int NOT NULL,
                    [QuestionCount] int NOT NULL,
                    [Reputation] int NOT NULL,
                    [UpVoteCount] int NOT NULL,
                    [ViewCount] int NOT NULL,
                    [BadgesGold] int NOT NULL,
                    [BadgesSilver] int NOT NULL,
                    [BadgesBronze] int NOT NULL,
                    [Rank] int NOT NULL,
                    [LastModifiedDate] datetime NOT NULL
                );
    
                CREATE UNIQUE INDEX  IF NOT EXISTS [IX_ApiEndpoint_UserId] ON [Users] ([ApiEndpoint], [UserId]);";
        }
        
    }


  [1]: http://sqlite.phxsoftware.com/
  [2]: https://stackapps.com/questions/543/sorep-trilogy-site-ranking-for-those-who-need-to-know