public void Migrate(IEnumerable <LocaleResourceEntry> entries, bool updateTouchedResources = false)
        {
            Guard.ArgumentNotNull(() => entries);

            if (!entries.Any() || !_languages.Any())
            {
                return;
            }

            using (var scope = new DbContextScope(_ctx, autoDetectChanges: false))
            {
                var langMap = _languages.ToDictionarySafe(x => x.UniqueSeoCode.EmptyNull().ToLower());

                var toDelete = new List <LocaleStringResource>();
                var toUpdate = new List <LocaleStringResource>();
                var toAdd    = new List <LocaleStringResource>();

                // remove all entries with invalid lang identifier
                var invalidEntries = entries.Where(x => x.Lang != null && !langMap.ContainsKey(x.Lang.ToLower()));
                if (invalidEntries.Any())
                {
                    entries = entries.Except(invalidEntries);
                }

                foreach (var lang in langMap)
                {
                    foreach (var entry in entries.Where(x => x.Lang == null || langMap[x.Lang.ToLower()].Id == lang.Value.Id))
                    {
                        bool isLocal;
                        var  db = GetResource(entry.Key, lang.Value.Id, toAdd, out isLocal);

                        if (db == null && entry.Value.HasValue() && !entry.UpdateOnly)
                        {
                            // ADD action
                            toAdd.Add(new LocaleStringResource {
                                LanguageId = lang.Value.Id, ResourceName = entry.Key, ResourceValue = entry.Value
                            });
                        }

                        if (db == null)
                        {
                            continue;
                        }

                        if (entry.Value == null)
                        {
                            // DELETE action
                            if (isLocal)
                            {
                                toAdd.Remove(db);
                            }
                            else
                            {
                                toDelete.Add(db);
                            }
                        }
                        else
                        {
                            if (isLocal)
                            {
                                db.ResourceValue = entry.Value;
                                continue;
                            }

                            // UPDATE action
                            if (updateTouchedResources || !db.IsTouched.GetValueOrDefault())
                            {
                                db.ResourceValue = entry.Value;
                                toUpdate.Add(db);
                                if (toDelete.Contains(db))
                                {
                                    toDelete.Remove(db);
                                }
                            }
                        }
                    }
                }

                // add new resources to context
                _resources.AddRange(toAdd);

                // remove deleted resources
                _resources.RemoveRange(toDelete);

                // update modified resources
                toUpdate.Each(x => _ctx.Entry(x).State = System.Data.Entity.EntityState.Modified);

                // save now
                int affectedRows = _ctx.SaveChanges();
            }
        }