using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.Entities; using Tango.Core.ExtensionMethods; namespace Tango.DataStore.EF { public class EFDataStoreCollection : IDataStoreCollection { public string Name { get; } public EFDataStoreCollection(String name) { Name = name; } public void Put(string key, T value) { Put(key, (object)value); } public void Put(string key, object value) { Put(key, DataStoreHelper.GetDataType(value), value); } public void Put(string key, DataType type, object value) { using (var db = ObservablesContext.CreateDefault()) { var globalItem = db.GlobalDataStoreItems.FirstOrDefault(x => x.CollectionName == Name && x.Key == key); if (globalItem != null) { if (globalItem.DataType != (int)type) { throw new InvalidOperationException("A global data store item exists with the same key, but different data type."); } } DataStoreItem item = db.DataStoreItems.SingleOrDefault(x => x.CollectionName == Name && x.Key == key); if (item == null) { item = new DataStoreItem(); db.DataStoreItems.Add(item); } item.CollectionName = Name; item.Key = key; item.DataType = (int)type; item.Value = EFDataStoreHelper.CreateBytes(type, value); item.IsSynchronized = false; item.LastUpdated = DateTime.UtcNow; item.IsDeleted = false; db.SaveChanges(); } } public T Get(string key) { return (T)Get(key, null); } public T Get(string key, T defaultValue) { return (T)Get(key, (object)defaultValue); } public object Get(string key) { return Get(key, null); } public object Get(string key, object defaultValue) { return GetItem(key, defaultValue).Value; } public IDataStoreItem GetItem(string key) { return GetItem(key, null); } public IDataStoreItem GetItem(string key, object defaultValue) { using (var db = ObservablesContext.CreateDefault()) { var item = db.DataStoreItems.SingleOrDefault(x => x.CollectionName == Name && x.Key == key && !x.IsDeleted); if (item == null) { var globalItem = db.GlobalDataStoreItems.SingleOrDefault(x => x.CollectionName == Name && x.Key == key); if (globalItem == null) { if (defaultValue == null) { throw new KeyNotFoundException("The specified data store key was not found."); } else { Put(key, defaultValue); return GetItem(key); } } else { return globalItem.ToDataStoreItem(); } } return item.ToDataStoreItem(); } } public List GetAll() { using (var db = ObservablesContext.CreateDefault()) { var localItems = db.DataStoreItems.Where(x => x.CollectionName == Name && !x.IsDeleted).ToList(); var globalItems = db.GlobalDataStoreItems.Where(x => x.CollectionName == Name).ToList(); foreach (var globalItem in globalItems.ToList()) { var localItem = localItems.FirstOrDefault(x => x.CollectionName == globalItem.CollectionName && x.Key == globalItem.Key); if (localItem != null) { globalItems.Remove(globalItem); } } return localItems.Select(x => x.ToDataStoreItem()).Concat(localItems.Select(x => x.ToDataStoreItem())).ToList(); } } public List GetUnsynchronized() { using (var db = ObservablesContext.CreateDefault()) { return db.DataStoreItems.Where(x => x.CollectionName == Name && !x.IsSynchronized).ToList().Select(x => x.ToDataStoreItem()).ToList(); } } public void Delete(string key) { using (var db = ObservablesContext.CreateDefault()) { db.Database.ExecuteSqlCommand($"DELETE FROM DATA_STORE_ITEMS WHERE COLLECTION_NAME = '{Name}' AND [KEY] = '{key}'"); } } public void DeleteAll() { using (var db = ObservablesContext.CreateDefault()) { db.Database.ExecuteSqlCommand($"DELETE FROM DATA_STORE_ITEMS WHERE COLLECTION_NAME = '{Name}'"); } } public int Count() { using (var db = ObservablesContext.CreateDefault()) { return db.DataStoreItems.Count(x => x.CollectionName == Name); } } } }