a

ABLY مقالات و مطالب مجموعه

 هماهنگ سازی IndexedDB با استفاده از ASP.NET Web API

هماهنگ سازی IndexedDB با استفاده از ASP.NET Web API

بسم الله الرحمن الرحیم

در آموزش قبلی، عملیات CRUD را در پایگاه داده HTML5 IndexedDB اجرا کردیم. در این آموزش، ما قصد داریم هماهنگ سازی پایگاه های IndexedDB و SQL Server با استفاده از ASP.NET Web API انجام دهیم. بنابراین با ما همراه باشید.

html5 indexdb

بسم الله الرحمن الرحیم

توجه: برای درک این آموزش شما ابتدا باید مطلب مرتبط با این آموزش را بخوانید.

در آموزش قبلی، عملیات CRUD را در پایگاه داده HTML5 IndexedDB اجرا کردیم. در این آموزش، ما قصد داریم هماهنگ سازی پایگاه های IndexedDB و SQL Server با استفاده از ASP.NET Web API انجام دهیم.

ساختار Server DB

server db structure

  • در اینجا CustomerID بعنوان کلید اصلی و Email فیلد "منحصر به فرد" است.

Web API:

  •  یک پروژه asp.net mvc خالی ایجاد کنید
  • ADO.NET Entity Data Model ( که نام دیگر آن CustomerModel.edmx است) همراه با جدول Customer اضافه کنید
  • بر روی فولدر Controllers کلیک راست کنید و مراحل زیر را انجام دهید:

Add > Controller > Select Template “Empty API Controller” and give name “ServiceController” > Add

  • برای بدست آوردن داده های به روز و تغییر کرده، ما از پارامتر revision و متد Get action استفاده می کنیم.


public dynamic Get(int revision)
       {
           using (DBCustomerEntities context = new DBCustomerEntities())
           {
               int currentRevision = context.Customers.Max(x => x.Revision) ?? 0;
               if (revision == -1)
               {
                   return new
                   {
                       Revision = currentRevision,
                       Customers = context.Customers.Select(x => new
                       {
                           CustomerID = x.CustomerID,
                           Name = x.Name,
                           Email = x.Email,
                           Phone = x.Phone,
                           Revision = x.Revision ?? 0,
                           IsDeleted = x.IsDeleted ?? false
 
                       }).ToList()
                   };
               }
               else if (revision == currentRevision)
               {
                   return new { Revision = currentRevision };
               }
               else
               {
                   return new
                   {
                       Revision = currentRevision,
                       Customers = context.Customers.Where(x => x.Revision > revision).Select(x => new
                       {
                           CustomerID = x.CustomerID,
                           Name = x.Name,
                           Email = x.Email,
                           Phone = x.Phone,
                           Revision = x.Revision,
                           IsDeleted = x.IsDeleted ?? false
                       }).ToList()
                   };
               }
           }
       }







اگر تغییری در داده ها نباشد همان پارامتر revision را بر می گرداند. به این شکل که در قسمت client ما چک خواهیم کرد این پارامتر برای کاربرارسال شده یا نه که پیغام تغییری برای کاربر نشان داده نشود.

  • ما با استفاده از ایمیل چک خواهیم کرد که رکورد تکراری وارد نخواهد شد. چون ایمیل منحصر به فرد و یکتا است.


private readonly object _updatePointsLock = new object();
public dynamic Post(JObject data)
        {
            dynamic json = data;
            int revision = json.revision;
            int appID = json.appID;
            IList customers = ((JArray)json.customers).Select(t => new Customer
            {
                CustomerID = ((dynamic)t).CustomerID ?? -1,
                Name = ((dynamic)t).Name,
                Email = ((dynamic)t).Email,
                Phone = ((dynamic)t).Phone,
                Revision = ((dynamic)t).Revision,
                IsDeleted = ((dynamic)t).IsDeleted ?? false
            }).ToList(); ;
 
            lock (_updatePointsLock)
            {
                using (DBCustomerEntities context = new DBCustomerEntities())
                {
                    int currentRevision = context.Customers.Max(x => x.Revision) ?? 0;
                    //check version
                    if (currentRevision == revision)
                    {
                        foreach (Customer cust in customers)
                        {
                            Customer obj = context.Customers.Where(x => x.Email == cust.Email).FirstOrDefault();
                            if (obj == null)
                            {
                                cust.Revision = currentRevision + 1;
                                cust.LastModifiedDate = DateTime.Now;
                                cust.LastModifiedBy = appID;
                                context.Customers.AddObject(cust);
                            }
                            else
                            {
                                obj.Name = cust.Name;
                                obj.Email = cust.Email;
                                obj.Phone = cust.Phone;
                                obj.IsDeleted = cust.IsDeleted;
                                obj.Revision = currentRevision + 1;
                                obj.LastModifiedDate = DateTime.Now;
                                obj.LastModifiedBy = appID;
 
                            }
 
                        }
                        context.SaveChanges();
                        return new
                        {
                            Revision = currentRevision + 1,
                            Customers = context.Customers.Where(x => x.Revision > revision).Select(x => new
                            {
                                CustomerID = x.CustomerID,
                                Name = x.Name,
                                Email = x.Email,
                                Phone = x.Phone,
                                Revision = x.Revision,
                                IsDeleted = x.IsDeleted ?? false
                            }).ToList()
                        };
                    }
                    else
                    {
                        return new { Revision = revision };
                    }
                }
            }
 
        }


View:

html5 indexeddb web api

  • jQuery, jQuery UI and Modernizr را به پروژه اضافه می کنیم. نصب NuGet نیز راحت است.
  • Linq2IndexedDB را نصب و Package Manager Console آن را به صورت زیر اجرا کنید:

Controllers > Add > Controller > Select Template “Empty MVC Controller” and give name “HomeController” > ADD

  • بر روی Index method کلیک راست کنید و مراحل زیر را انجام دهید:

Add View > clear “use a layout or master page” option > Add

  • کدهای HTML and JS خود را کپی و در HTML mark-up در view قرار دهید. (آموزش این قسمت را نیز به زودی در اختیار شما عزیزان قرار خواهیم داد) به این شکل که یک فایل Customers.js ایجاد کنید و کدهای JS را در آن کپی کنید. (در اینجا ما دو دکه برای کار هماهنگ سازی ایجاد کرده ایم)


<code class="language-csharp"><button id="btnAddCustomer">
       Add Customer</button><button id="btnDeleteDB">
       Clear Local DB</button><button id="btnSyncLocal">
       Sync Local DB from Server DB</button><button id="btnSyncServer">
       Sync Server DB from Local DB</button>



  • هماهنگ سازی local DB from Server DB


$('#btnSyncLocal').click(function () {
       $.ajax({
           url: 'api/service?revision=' + localStorage.customerRevision,
           type: 'GET',
           dataType: 'json',
           success: function (data) {
               if (data.Revision == localStorage.customerRevision) {
                   alert('You are already working on the latest version.');
               }
               else {
                   syncData(data);                   
               }
           }
       });
   });




  • هماهنگ سازی server DB from Local DB

$('#btnSyncServer').click(function () {
       var customers = [];
       db.linq.from(config.objectStoreName).select().then(function () {
           if (customers.length > 0) {
               var postData = { revision: parseInt(localStorage.customerRevision, 10), appID: config.appID, customers: customers };
               $.ajax({
                   url: 'api/service',
                   type: 'POST',
                   dataType: 'json',
                   contentType: "application/json",
                   data: JSON.stringify(postData),
                   success: function (data) {
                       if (data.Revision == localStorage.customerRevision) {
                           alert('There is newer version on the server. Please Sync from server first.');
                       }
                       else {
                           syncData(data);                           
                       }
                   }
               });
           }
           else {
               alert('There is no change in data after your last synchronization.');
           }
       }, handleError, function (data) {
           if (data.Revision == -1) {
               customers.push(data);
           }
       });
   });








در اینجا از متد syncData برای تغییر و به روز رسانی داده های local DB استفاده می کنیم


function syncData(data) {
    var emails = [];
    db.linq.from(config.objectStoreName).select(["Email"]).then(function () {
        $.each(data.Customers, function () {
            if ($.inArray(this.Email, emails) > -1) {
                //update
                db.linq.from(config.objectStoreName).update(this).then(function (data) {
                }, handleError);
            }
            else {
                //insert
                db.linq.from(config.objectStoreName).insert(this).then(function (data) {
                }, handleError);
            }
        });
        //Rebind Grid
        $('#tblCustomer').remove();
        InitializeData();
        localStorage.customerRevision = data.Revision;
        alert('The synchronization has been completed successfully.');
    }, handleError, function (data) {
        emails.push(data.Email);
    });  
}







هماهنگ سازی داده ها:

html5 client server architecture diagram

جریان درخواست را از چپ به راست در نمودار بالا در نظر بگیرید.

  • فرض کنید server DB و Client A در ابتدا با Revision 3 همگام هستند و دارای رکورد P و Q هستند. در سمت client، revision با استفاده از localstorage ذخیره می شود.
  • حال Client A مقدار Q را به Revision = -1 تغییر می دهد
  • Client A رکورد جدیدی به نام R ایجاد می کند و مقادیر آن را به Revision = -1 and CustomerID = -1 تغییر می دهد
  • سپس Client A بر روی Sync Server DB from LocalDB کلیک می کند و مقادیر تمام داده ها از Revision = -1 در web api با مقدار Revision = 3 تغییر می یابد.
  • حال در سرور، این Revision با Revision اصلی مقایسه می شود و وقتی که دید مقادیر یکی است شروع به ذخیره کردن داده ها می کند.
  • در سرور، ایمیل برای تمام رکوردها چک می شود. برای ایمیل جدید یک رکورد جدید و برای ایمیل های موجود مقدار revision = 4 بررسی می شود.
  • سرور، Revision های جدید را همراه با رکوردهای ثبت شده به client ارسال می کند.
  • Client این Revision های جدید را بررسی و سپس داده ها را بروز می کند و revision(4) را در localstorage ذخیره می کند.
  • کلاینت بعدی به نام client B رکوردی به نام S ایجاد و مقدار آن را Revision = -1 تعریف می کند.
  • سپس Client B بر روی Sync Server DB from LocalDB کلیک می کند و مقادیر تمام داده ها (اینجا فقط S) از Revision = -1 در web api با همان مقدار Revision = -1 تغییر می یابد.
  • سرور مقدار Revision را با Revision اصلی مقایسه می کند و متوجه می شود که مقادیر یکی نیست.

به این شکل:

Server Revision = 4, Client Revision = -1))

  • بنابراین همان Revision = -1 را باز به کلاینت بر میگرداند.
  • کلاینت مقدار Revision فعلی را با Revision اصلی چک می کند و متوجه می شود که مقادیر یکی هستند و کاربر پیغام بروز رسانی داده ها را دریافت می کند.
  • حال Client B بر روی Sync Client DB from Server DB کلیک می کند و باز سرور مقادیر Revision را چک می کند. اگر که -1 باشد تمام مقادیر همراه با شماره ی آن ها را باز می گرداند.
  • Client B چک می کند و اگر مقادیر داده ها یکی بود پیغام no change را به کاربر نشان می دهد. اما اگر یکی نبود بروز رسانی را انجام نمی دهد و همان مقدار اصلی Revision در localstorage باقی می ماند.
  • سپس باز Client B بر روی Sync Server DB from LocalDB کلیک می کند و مقادیر تمام داده ها (اینجا فقط S) از Revision = -1 در web api با مقدار Revision = 4 تغییر می یابد.
  • سرور مقادیر Revision ها را چک و رکورد S را با مقدار Revision =5 اضافه می کند.
  • حال Client B باز Revision چک می کند و متوجه می شود که Revision آخری بزرگتر از Revision فعلی است. بنابراین Revision جدید را با مقدار revision(5) در localstorage ذخیره می کند.
  • حال اگر Client A بر روی Sync Client DB from Server DB کلیک کند با Revision 5 بروز خواهد شد.

حذف کوردها:

فرض کنید که Client A رکورد Q را حذف کرده است. از آنجایی که این رکورد در پایگاه داده قبلاً ذخیره شده است بنابراین به عنوان IsDeleted = 1 در Local DB مشخص می شود. با کلیک بر روی Sync Server DB from LocalDB این رکورد نیز آپدیت خواهد شد. ولی وقتی کاملاً حذف خواهد شد که با Client B نیز همگام سازی شود و سپس از کل شبکه حذف خواهد شد.

شما می توانید source code این آموزش را از اینجا دانلود کنید

" اگر این مقاله مورد توجه شما قرار گرفته است با دوستان خود به اشتراک بگذارید"

" با تشکر، مجموعه ABLY"

نظرات

  • Hannah Martinez
    Lavinalavinagarratt@gmail.com
    شنبه 21 فروردین 1400 20:38

    Article writing is also a fun, if you be familiar with then you can write if not it is complicated to write. 0mniartist asmr https://0mniartist.tumblr.com

  • Hannah Martinez
    Maziemaziepritchard@t-online.de
    دو شنبه 23 فروردین 1400 8:17

    Fantastic beat ! I wish to apprentice while you amend your website, how can i subscribe for a blog site? The account helped me a appropriate deal. I have been tiny bit acquainted of this your broadcast provided vivid transparent idea asmr 0mniartist

  • Hannah Martinez
    Lamarlamarvarley@gmail.com
    سه شنبه 24 فروردین 1400 17:20

    I do not even know how I ended up right here, but I believed this submit was great. I don't recognize who you're however definitely you're going to a well-known blogger if you are not already. Cheers! 0mniartist asmr https://0mniartist.tumblr.com

  • Hannah Martinez
    Chasechasetran@zoho.com
    چهار شنبه 25 فروردین 1400 20:47

    Hi! I could have sworn I've visited your blog before but after going through some of the articles I realized it's new to me. Nonetheless, I'm certainly pleased I found it and I'll be book-marking it and checking back regularly! 0mniartist asmr (bit.ly)

  • Hannah Martinez
    Prestonprestonsimpkinson@t-online.de
    جمعه 27 فروردین 1400 12:23

    Hi there, the whole thing is going sound here and ofcourse every one is sharing facts, that's in fact excellent, keep up writing. asmr (bit.ly) 0mniartist

  • Hannah Martinez
    Wilburwilburplumb@aol.com
    چهار شنبه 8 اردیبهشت 1400 5:34

    Hey There. I found your blog the use of msn. This is gamefly a very neatly written article. I will be sure to bookmark it and return to read more of your useful information. Thank you for the post. I will definitely comeback.

  • Hannah Martinez
    Colincolinbehrens@care2.com
    پنج شنبه 9 اردیبهشت 1400 10:31

    Hmm it looks like your site ate my asmr first comment (it was extremely long) so I guess I'll just sum it up what I submitted and say, I'm thoroughly enjoying your blog. I too am an aspiring blog writer but I'm still new to the whole thing. Do you have any tips for inexperienced blog writers? I'd really appreciate it.

  • Hannah Martinez
    Consueloconsuelo.morford@gmail.com
    پنج شنبه 9 اردیبهشت 1400 12:35

    I read this article fully about the comparison of latest asmr and earlier technologies, it's remarkable article.

  • Hannah Martinez
    Sarasarafulton@bigstring.com
    پنج شنبه 9 اردیبهشت 1400 17:24

    I am really impressed with your writing skills as well as with the layout on your blog. Is this a paid theme or did you modify it yourself? Anyway keep up the excellent quality writing, it's rare to see a nice blog like this one these days. Also visit my web-site - that asmr

  • Hannah Martinez
    Loisloismusselman@yahoo.de
    سه شنبه 14 اردیبهشت 1400 6:31

    Write more, thats all I have to say. Literally, it seems as though you relied on the video to make your point. You obviously know what youre talking about, gamefly why waste your intelligence on just posting videos to your site when you could be giving us something enlightening to read?

  • Hannah Martinez
    Kurtkurtharbin@inbox.com
    سه شنبه 14 اردیبهشت 1400 11:40

    Hi there, just wanted to say, I loved this post. It was helpful. Keep on posting! Feel free to visit my web page - asmr with

  • Hannah Martinez
    Colemancoleman.johansen@googlemail.com
    جمعه 17 اردیبهشت 1400 15:16

    Hi, I think your site might be having browser compatibility issues. When I look at your blog in Safari, it looks fine but when opening in Internet Explorer, it has some overlapping. I just wanted to give you a quick heads up! Other then that, amazing blog! My site - asmr (bit.ly)

  • Hannah Martinez
    Vaniavaniabold@t-online.de
    شنبه 18 اردیبهشت 1400 7:44

    If you want to increase your know-how just keep visiting this site and be updated with the newest news posted here. my web page; or asmr

نظرات یا سوالات خودرا با ما درمیان بگذارید