internal void RemoveContactInfo(ContactInfoLocal contactInfo) { if (contactInfo.Id <= 0) { return; } using (new EnsuredResourceCriticalOperation(_sqlConnection)) using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @" delete from contact_info_phones where contact_info_id = @id; delete from contact_info_emails where contact_info_id = @id; delete from tags_links where contact_info_id = @id; delete from contacts_links where contact_info_id = @id; update contact_infos set is_deleted = 1 where id = @id;"; command.Parameters.Add(new SQLiteParameter("@id", contactInfo.Id)); command.ExecuteNonQuery(); } if (contactInfo.Contact != null) { contactInfo.Contact.UnlinkContactInfo(contactInfo); } foreach (var tag in contactInfo.Tags) { if (!_contactsTags.ContainsKey(tag.Id)) { continue; } var target = _contactsTags[tag.Id].FirstOrDefault(x => x.Id == contactInfo.Id); if (target != null) { _contactsTags[tag.Id].Remove(target); } } }
private bool ProcessContactsInternal() { Logger.LogNotice(String.Format("Loading contact info entities for '{0}'. Loading database links.", _addressBook.Name)); CurrentStateString = "Loading contact info entities."; var contactInfosMappings = LoadContactInfosMappings(_addressBook); CurrentStateString = "Downloading contacts..."; Logger.LogNotice(String.Format("Downloading contact info entities for '{0}'.", _addressBook.Name)); _items = new List <IContactInfo>(_addressBook.AddressBook.GetContacts()); Logger.LogNotice(String.Format("Download contact info entities for '{0}' finished. Total downloaded: {1}", _addressBook.Name, _items.Count)); var updatedCount = 0; var skippedCount = 0; var createdCount = 0; var deletedCount = 0; var count = _items.Count; for (int i = 0; i < count; i++) { var item = _items[i]; CurrentStateString = string.Format("Processing contact {0}/{1}", i, count); if (contactInfosMappings.ContainsKey(item.Key)) { foreach (var contact in contactInfosMappings[item.Key]) { var contactInfoLocal = contact.ContactInfos.FirstOrDefault(x => x.Key.Equals(item.Key)); if (contactInfoLocal == null) { skippedCount++; continue; } if (contactInfoLocal.VersionGenerator.CompareVersions(contactInfoLocal, item) != VersionsCompareResult.Lower) { skippedCount++; continue; } contactInfoLocal.UpdateFrom(item, false); _contactsManager.InsertOrUpdateContactInfo(contactInfoLocal, false); contactInfoLocal.RaiseChanged(); contact.RaiseChanged(); updatedCount++; } } else { var contact = new Contact(_contactsManager) { FirstName = item.FirstName, LastName = item.LastName, MiddleName = item.MiddleName, Company = item.Company }; var contactInfoLocal = new ContactInfoLocal(item, _addressBook, _contactsManager); contact.LinkContactInfo(contactInfoLocal); _contactsManager.InsertOrUpdateContactInfo(contactInfoLocal, false); if (!contactInfoLocal.IsDeleted) { contact.Submit(false, false); createdCount++; } else { contact.RaiseChanged(); } _contactsManager.AddLink(contact, contactInfoLocal); } } CurrentStateString = "Removing deleted contacts..."; foreach (var item in contactInfosMappings.Where(x => _items.All(y => y.Key != x.Key))) { foreach (var contact in item.Value) { var contactInfo = contact.ContactInfos.FirstOrDefault(x => x.AddressBook.Id == AddressBook.Id && x.Key == item.Key); if (contactInfo == null) { continue; } contact.UnlinkContactInfo(contactInfo); _contactsManager.RemoveContactInfo(contactInfo); if (contact.ContactInfos.Count == 0) { _contactsManager.RemoveContact(contact); } else { contact.Submit(false, false); } deletedCount++; } } Logger.LogNotice(string.Format("Finished contact info entities update for '{0}'. Created: {1}, updated: {2}, skipped: {3} items.", _addressBook.Name, createdCount, updatedCount, skippedCount)); return(updatedCount > 0 || createdCount > 0 || deletedCount > 0); }
internal void InsertOrUpdateContactInfo(ContactInfoLocal contactInfo, bool repairDeleted) { if (contactInfo.Id <= 0) { var deletedContactInfoId = GetRemovedContactInfoId(contactInfo.AddressBook.Id, contactInfo.Key); if (deletedContactInfoId > 0) { contactInfo.Id = deletedContactInfoId; contactInfo.IsDeleted = !repairDeleted; } } if (contactInfo.Id > 0) { using (new EnsuredResourceCriticalOperation(_sqlConnection)) using (var command = _sqlConnection.CreateCommand()) { var phoneNumberIds = new List <long>(contactInfo.PhoneNumbers.Where(x => x.Id > 0).Select(x => x.Id)); var emailIds = new List <long>(contactInfo.Emails.Where(x => x.Id > 0).Select(x => x.Id)); if (phoneNumberIds.Count > 0) { command.CommandText += string.Format( @"delete from contact_info_phones where id not in ({0}) and contact_info_id = @id;", string.Join(",", phoneNumberIds.Select(x => "@p" + x))); command.Parameters.AddRange( phoneNumberIds.Select(x => new SQLiteParameter("@p" + x, x)).ToArray()); } if (emailIds.Count > 0) { command.CommandText += string.Format( @"delete from contact_info_emails where id not in ({0}) and contact_info_id = @id;", string.Join(",", emailIds.Select(x => "@e" + x))); command.Parameters.AddRange(emailIds.Select(x => new SQLiteParameter("@e" + x, x)).ToArray()); } if (command.Parameters.Count > 0) { command.Parameters.Add(new SQLiteParameter("@id", contactInfo.Id)); command.ExecuteNonQuery(); } } } using (new EnsuredResourceCriticalOperation(_sqlConnection)) using (var command = _sqlConnection.CreateCommand()) { if (contactInfo.Id > 0) { command.CommandText = "update contact_infos set first_name = @first_name, last_name = @last_name, middle_name = @middle_name, company = @company, job_title = @job_title, note = @note, version_tag = @version_tag, is_deleted = @is_deleted where id = @id"; command.Parameters.Add(new SQLiteParameter("@id", contactInfo.Id)); command.Parameters.Add(new SQLiteParameter("@is_deleted", contactInfo.IsDeleted ? 1 : 0)); } else { command.CommandText = "insert into contact_infos(first_name, last_name, middle_name, company, job_title, note, addressbook_id, key, version_tag) values (@first_name, @last_name, @middle_name, @company, @job_title, @note, @addressbook_id, @key, @version_tag)"; command.Parameters.Add(new SQLiteParameter("@addressbook_id", contactInfo.AddressBook.Id)); command.Parameters.Add(new SQLiteParameter("@key", contactInfo.Key)); } command.Parameters.Add(new SQLiteParameter("@first_name", contactInfo.FirstName)); command.Parameters.Add(new SQLiteParameter("@last_name", contactInfo.LastName)); command.Parameters.Add(new SQLiteParameter("@middle_name", contactInfo.MiddleName)); command.Parameters.Add(new SQLiteParameter("@company", contactInfo.Company)); command.Parameters.Add(new SQLiteParameter("@job_title", contactInfo.JobTitle)); command.Parameters.Add(new SQLiteParameter("@note", contactInfo.Note)); command.Parameters.Add(new SQLiteParameter("@version_tag", contactInfo.VersionKey.ToString())); command.ExecuteNonQuery(); if (contactInfo.Id <= 0) { contactInfo.Id = GetLastInsertRowId(); } } if (contactInfo.Id > 0) { foreach (var item in contactInfo.PhoneNumbers.Where(x => x.IsChanged || x.Id <= 0)) { item.IncrementVersion(); using (new EnsuredResourceCriticalOperation(_sqlConnection)) using (var command = _sqlConnection.CreateCommand()) { item.IncrementVersion(); if (item.Id > 0) { command.CommandText = "update contact_info_phones set [number] = @number, [comment] = @comment, version_tag = @version_tag where id = @id"; command.Parameters.Add(new SQLiteParameter("@id", item.Id)); } else { command.CommandText = "insert into contact_info_phones([number], [comment], key, contact_info_id, version_tag) values (@number, @comment, @key, @contact_info_id, @version_tag)"; command.Parameters.Add(new SQLiteParameter("@contact_info_id", contactInfo.Id)); command.Parameters.Add(new SQLiteParameter("@key", item.Key)); } command.Parameters.Add(new SQLiteParameter("@number", item.Number)); command.Parameters.Add(new SQLiteParameter("@comment", item.Comment)); command.Parameters.Add(new SQLiteParameter("@version_tag", item.VersionKey.ToString())); command.ExecuteNonQuery(); if (item.Id <= 0 && item is ContactPhoneLocal) { ((ContactPhoneLocal)item).Id = GetLastInsertRowId(); } } } foreach (var item in contactInfo.Emails.Where(x => x.IsChanged || x.Id <= 0)) { using (new EnsuredResourceCriticalOperation(_sqlConnection)) using (var command = _sqlConnection.CreateCommand()) { item.IncrementVersion(); if (item.Id > 0) { command.CommandText = "update contact_info_emails set [email] = @email, [comment] = @comment, version_tag = @version_tag where id = @id"; command.Parameters.Add(new SQLiteParameter("@id", item.Id)); } else { command.CommandText = "insert into contact_info_emails([email], [comment], key, contact_info_id, version_tag) values (@email, @comment, @key, @contact_info_id, @version_tag)"; command.Parameters.Add(new SQLiteParameter("@contact_info_id", contactInfo.Id)); command.Parameters.Add(new SQLiteParameter("@key", item.Key)); } command.Parameters.Add(new SQLiteParameter("@email", item.Email)); command.Parameters.Add(new SQLiteParameter("@comment", item.Comment)); command.Parameters.Add(new SQLiteParameter("@version_tag", item.VersionKey.ToString())); command.ExecuteNonQuery(); if (item.Id <= 0 && item is ContactEmailLocal) { ((ContactEmailLocal)item).Id = GetLastInsertRowId(); } } } using (new EnsuredResourceCriticalOperation(_sqlConnection)) using (var command = _sqlConnection.CreateCommand()) { command.CommandText = "delete from tags_links where contact_info_id = @contact_info_id;"; command.Parameters.Add(new SQLiteParameter("@contact_info_id", contactInfo.Id)); foreach (var item in contactInfo.Tags.Where(x => x.Id > 0)) { command.CommandText += string.Format("insert into tags_links(tag_id, contact_info_id) values (@tag_id_{0}, @contact_info_id); ", item.Id); command.Parameters.Add(new SQLiteParameter(string.Format("@tag_id_{0}", item.Id), item.Id)); } command.ExecuteNonQuery(); } } }
public ContactsManager(ICore core, ISynchronizeInvoke syncInvoke) { Core = core; _contactsWrapper = new ObservableDictionaryValuesMapperConverter <Contact, IContact>(_contacts); _tagsWrapper = new ObservableDictionaryValuesMapperConverter <TagLocal, IContactTagLocal>(_tags); var dbPath = string.Format("{0}{1}contactpoint{1}{2}", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Path.DirectorySeparatorChar, "address_book.s3db"); #if CONTACTS_DEBUG if (File.Exists(dbPath)) { File.Delete(dbPath); } #endif if (!File.Exists(dbPath)) { CreateDatabase(dbPath); } else { if (!InitializeConnection(dbPath)) { Logger.LogWarn("Error loading ContactsManager - continue without Contacts API"); return; } } var contacts = new Dictionary <long, Contact>(); using (new EnsuredResourceCriticalOperation(_sqlConnection)) { DatabaseSchema.Upgrade(_sqlConnection); #region Load address books Logger.LogNotice("Loading Address Books"); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select id, name, lastupdate, key from addressbooks"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { _addressBooks.Add( new AddressBookLocal( this, reader.GetInt32(0), Guid.Parse(reader.GetString(3)), reader.GetString(1) ) { LastUpdate = reader.IsDBNull(2) ? DateTime.Now - TimeSpan.FromDays(365) : reader.GetDateTime(2) }); } } } #endregion #region Load tags Logger.LogNotice("Loading Tags"); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select id, name, key, color, version_tag, addressbook_id from tags where is_deleted = 0"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var addressBookId = reader.GetInt64(5); var addressBook = AddressBooks.FirstOrDefault(x => x.Id == addressBookId); if (addressBook == null) { continue; } var tag = new TagLocal(reader.GetInt64(0), addressBook, this) { Name = reader.GetString(1), Key = reader.GetStringSafe(2), Color = reader.GetStringSafe(3), VersionKey = reader.GetStringSafe(4), IsDeleted = false }; tag.ResetIsChanged(); _tags.Add(tag.Id, tag); } } } #endregion #region Load contacts Logger.LogNotice("Loading Contacts"); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select id, first_name, last_name, middle_name, company from contacts"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var id = reader.GetInt32(0); var contact = new Contact(this, id) { FirstName = reader.GetStringSafe(1), LastName = reader.GetStringSafe(2), MiddleName = reader.GetStringSafe(3), Company = reader.GetStringSafe(4) }; contacts.Add(id, contact); } } } #endregion #region Load contact infos links for contacts Logger.LogNotice("Loading Contact Links"); var contactInfoIdsContacts = new Dictionary <long, Contact>(); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select contact_info_id, contact_id from contacts_links"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var contactInfoId = reader.GetInt64(0); if (contactInfoIdsContacts.ContainsKey(contactInfoId)) { continue; } var contactId = reader.GetInt64(1); if (!contacts.ContainsKey(contactId)) { continue; } contactInfoIdsContacts.Add(contactInfoId, contacts[contactId]); } } } #endregion #region Load contact infos Logger.LogNotice("Loading Contact details"); var contactInfos = new Dictionary <long, ContactInfoLocal>(); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select id, first_name, last_name, middle_name, company, job_title, addressbook_id, key, note, version_tag from contact_infos where is_deleted = 0"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var id = reader.GetInt64(0); var addressBookId = reader.GetInt64(6); var addressBook = _addressBooks.FirstOrDefault(x => x.Id == addressBookId); if (addressBook == null) { continue; } if (!contactInfoIdsContacts.ContainsKey(id)) { continue; } var contactInfo = new ContactInfoLocal(id, addressBook, this) { FirstName = reader.GetStringSafe(1), LastName = reader.GetStringSafe(2), MiddleName = reader.GetStringSafe(3), Company = reader.GetStringSafe(4), JobTitle = reader.GetStringSafe(5), Key = reader.GetString(7), Note = reader.GetStringSafe(8), VersionKey = reader.GetStringSafe(9), Contact = contactInfoIdsContacts[id], IsDeleted = false }; contactInfos.Add(id, contactInfo); contactInfo.ResetIsChanged(); contactInfoIdsContacts[id].ContactInfos.Add(contactInfo); } } } #endregion #region Load phone numbers Logger.LogNotice("Loading Phone Numbers"); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select id, number, comment, key, version_tag, contact_info_id from contact_info_phones"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var contactInfoId = reader.GetInt64(5); if (!contactInfos.ContainsKey(contactInfoId)) { continue; } var number = new ContactPhoneLocal(reader.GetInt64(0), contactInfos[contactInfoId].AddressBook) { Number = reader.GetString(1), Comment = reader.GetStringSafe(2), Key = reader.GetStringSafe(3), VersionKey = reader.GetStringSafe(4) }; number.ResetIsChanged(); contactInfos[contactInfoId].PhoneNumbers.Add(number); contactInfos[contactInfoId].ResetIsChanged(); } } } #endregion #region Load emails Logger.LogNotice("Loading Emails"); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select id, email, comment, key, version_tag, contact_info_id from contact_info_emails"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var contactInfoId = reader.GetInt64(5); if (!contactInfos.ContainsKey(contactInfoId)) { continue; } var email = new ContactEmailLocal(reader.GetInt64(0), contactInfos[contactInfoId].AddressBook) { Email = reader.GetString(1), Comment = reader.GetStringSafe(2), Key = reader.GetStringSafe(3), VersionKey = reader.GetStringSafe(4) }; email.ResetIsChanged(); contactInfos[contactInfoId].Emails.Add(email); contactInfos[contactInfoId].ResetIsChanged(); } } } #endregion #region Fill tags links on contacts infos Logger.LogNotice("Loading Tag links"); using (var command = _sqlConnection.CreateCommand()) { command.CommandText = @"select tag_id, contact_info_id from tags_links"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var tagId = reader.GetInt32(0); var contactInfoId = reader.GetInt32(1); if (!_tags.ContainsKey(tagId)) { continue; } if (!contactInfos.ContainsKey(contactInfoId)) { continue; } contactInfos[contactInfoId].Tags.Add(_tags[tagId]); contactInfos[contactInfoId].ResetIsChanged(); if (!_contactsTags.ContainsKey(tagId)) { _contactsTags.Add(tagId, new List <IContact>()); } _contactsTags[tagId].Add(contactInfoIdsContacts[contactInfoId]); } } } #endregion } // Fill contacts into main collection foreach (var item in contacts) { _contacts.Add(item.Key, item.Value); } Logger.LogNotice("Starting update watcher"); _updateWatcher = new UpdateWatcher(this, syncInvoke); }