简体   繁体   中英

Multiple row insertion Azure Mobile Services Offline, sync with the backend

Is it possible to modify Table Controllers in Azure Mobile Services .Net backend to handle multi-insertion per http request? After coming back online it takes 2+ minutes for my app to sync its data. over 70% of the 2 minute is wasted over the network handshaking overhead.

I had to do something similar. My app creates around 10,000 new rows every time a user creates a new project so I made a custom controller in my Mobile Service to accept this. After the 10,000 entities are inserted I pull all of them back down to the local sync database.

I first created a custom controller.

public class BatchInsertController : ApiController
{
    DbContext context;

    protected override void Initialize(HttpControllerContext controllerContext)
    {
        base.Initialize(controllerContext);
        this.context = new DbContext();
    }

    [HttpPost]
    public async Task<bool> BatchInsert(List<Entity> entities)
    {
        try
        {
            this.context.Entities.AddRange(entities);
            await this.context.SaveChangesAsync();

            return true;
        }
        catch (System.Exception ex)
        {
            Trace.WriteLine("Error: " + ex);
            return false;
        }
    }

}

Then I would call this custom controller method from my client code.

var entities = new List<Entity>();
// Add a bunch of entities to the list...

foreach (List<Entity> chunkedEntities in entities.ChunksOf(1000))
{
    var response = await _client.InvokeApiAsync<List<Entity>, bool>("batchinsert", chunkedEntities);
}

I would have over 10,000 records at a time so I created an extension method to chunk the list and send 1,000 records at a time.

public static IEnumerable<IList<T>> ChunksOf<T>(this IEnumerable<T> sequence, int size)
{
    List<T> chunk = new List<T>(size);
    foreach (T element in sequence)
    {
        chunk.Add(element);
        if (chunk.Count == size)
        {
            yield return chunk;
            chunk = new List<T>(size);
        }
    }
    if (chunk.Any())
    {
        yield return chunk;
    }
}

After that I just did a PullAsync() on my local db. I came up with this after reading through this article.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM