public static IterateResult RunUnorderedWorkload(IList src, int smalllist, int dop, Func <object, int, int, object[], object> body) #pragma warning restore IDE0060 // Remove unused parameter { int idx = 0; List <Exception> errors = new(); List <object> data = new(); if (src.Count <= smalllist) { foreach (var a in src) { try { var lidx = Interlocked.Add(ref idx, 1); var d = body.Invoke(a, lidx - 1, src.Count - lidx, Array.Empty <object>()); lock (data) { data.Add(d); } } catch (Exception ex) { errors.Add(ex); } } } else { var ss = CEF.CurrentServiceScope; _ = Parallel.ForEach(src.Cast <object>(), (a) => { try { using (CEF.UseServiceScope(ss)) { var lidx = Interlocked.Add(ref idx, 1); var d = body.Invoke(a, lidx - 1, src.Count - lidx, Array.Empty <object>()); lock (data) { data.Add(d); } } } catch (Exception ex) { lock (errors) { errors.Add(ex); } } }); } return(new IterateResult(data.ToArray(), errors.ToArray())); }
string IDataErrorInfo.this[string columnName] { get { using (CEF.UseServiceScope(_initScope)) { return(_errorSource?[columnName]); } } }
public static void RunWorkloadFunctions(params Action[] args) { var ss = CEF.CurrentServiceScope; Parallel.ForEach(args, (a) => { using (CEF.UseServiceScope(ss)) { a.Invoke(); } }); }
protected override object AddNewCore() { using (CEF.UseServiceScope(OwningScope)) { // We rely on construction of a new DynamicBindable that has the same shape as the first item in the collection, if any exist if (this.Any()) { var f = this.First(); var wot = f.Wrapped?.GetWrappedObject()?.GetType(); if (wot != null) { var no = Activator.CreateInstance(wot); var wno = CEF.IncludeObject(no, ObjectState.Added); var nod = wno.AsDynamicBindable(); base.Add(nod); return(nod); } } // If none exist, need to rely on the "default schema" provided if (BaseItemType != null) { var no = Activator.CreateInstance(BaseItemType); var wno = CEF.IncludeObject(no, ObjectState.Added); var iw = wno.AsInfraWrapped(); var nod = wno.AsDynamicBindable(); if (ExternalSchema != null) { foreach (var e in ExternalSchema) { if (!iw.HasProperty(e.Key)) { iw.SetValue(e.Key, null, e.Value); } } } base.Add(nod); return(nod); } // No default schema? It's an error situation. throw new InvalidOperationException("Cannot add a new item to the GenericBindableSet collection since there's no object definition available."); } }
protected override void RemoveItem(int index) { var i = this[index]; RemoveTracking(new DynamicBindable[] { this[index] }); base.RemoveItem(index); using (CEF.UseServiceScope(OwningScope)) { var uw = i.Wrapped; if (uw != null) { CEF.DeleteObject(uw); } } SetDirty(); }
public override void SetValue(object component, object value) { using (CEF.UseServiceScope(_ss)) { DynamicWithBag iw = null; if (component is DynamicBindable db) { iw = db.Wrapped; } if (iw == null) { iw = _iw; } iw.SetValue(_name, value, _dt); } }
public override void ResetValue(object component) { using (CEF.UseServiceScope(_ss)) { DynamicWithBag iw = null; if (component is DynamicBindable db) { iw = db.Wrapped; } if (iw == null) { iw = _iw; } iw.SetValue(_name, iw.GetOriginalValue(_name, false), _dt); } }
public static void RunWorkloadFunctions(bool ordered, params Action[] args) { if (ordered) { foreach (var a in args) { a.Invoke(); } } else { var ss = CEF.CurrentServiceScope; Parallel.ForEach(args, (a) => { using (CEF.UseServiceScope(ss)) { a.Invoke(); } }); } }
public override object GetValue(object component) { using (CEF.UseServiceScope(_ss)) { DynamicWithBag iw = null; if (component is DynamicBindable db) { iw = db.Wrapped; } if (iw == null) { iw = _iw; } if (iw.HasProperty(_name)) { return(iw.GetValue(_name)); } return(null); } }
public static void Benchmark1(int total_parents, List <long> testTimes, List <long> testTimes2, ref int rowcount, ref int rowcount2) { var watch = new System.Diagnostics.Stopwatch(); watch.Start(); using (CEF.NewServiceScope()) { var people = new EntitySet <PersonWrapped>(); for (int parentcnt = 1; parentcnt <= total_parents; ++parentcnt) { var parent = new PersonWrapped() { Name = $"NP{parentcnt}", Age = (parentcnt % 60) + 20, Gender = (parentcnt % 2) == 0 ? "F" : "M" }; parent.Phones.Add(new Phone() { Number = "888-7777", PhoneTypeID = PhoneType.Mobile }); parent.Phones.Add(new Phone() { Number = "777-6666", PhoneTypeID = PhoneType.Work }); if ((parentcnt % 12) == 0) { CEF.NewObject(new Phone() { Number = "666-5555", PhoneTypeID = PhoneType.Home }); } else { parent.Phones.Add(new Phone() { Number = "777-6666", PhoneTypeID = PhoneType.Home }); } rowcount += 4; for (int childcnt = 1; childcnt <= (parentcnt % 4); ++childcnt) { var child = CEF.NewObject(new PersonWrapped() { Name = $"NC{parentcnt}{childcnt}", Age = parent.Age - 20, Gender = (parentcnt % 2) == 0 ? "F" : "M" , Phones = new Phone[] { new Phone() { Number = "999-8888", PhoneTypeID = PhoneType.Mobile } } }); parent.Kids.Add(child); rowcount += 2; } people.Add(parent); } CEF.DBSave(); } testTimes.Add(watch.ElapsedMilliseconds); watch.Restart(); // For purposes of benchmarking, treat this as a completely separate operation using (var ss = CEF.NewServiceScope()) { // For everyone who's a parent of at least 30 yo, if at least 2 children of same sex, remove work phone, increment age var people = new EntitySet <Person>().DBRetrieveSummaryForParents(30); Parallel.ForEach((from a in people let d = a.AsDynamic() where d.MaleChildren > 1 || d.FemaleChildren > 1 select a).ToList(), (p) => { using (CEF.UseServiceScope(ss)) { p.Age += 1; var phones = new EntitySet <Phone>().DBRetrieveByOwner(p.PersonID, PhoneType.Work); if (phones.Any()) { CEF.DeleteObject(phones.First()); } } }); rowcount2 += CEF.DBSave().Count(); } watch.Stop(); testTimes2.Add(watch.ElapsedMilliseconds); }
public static void Benchmark3SavePer(int total_parents, List <long> testTimes, List <long> testTimes2, ref int rowcount, ref int rowcount2) { var watch = new System.Diagnostics.Stopwatch(); watch.Start(); long cnt1 = 0; var people = new EntitySet <PersonWrapped>(); Parallel.For(1, total_parents + 1, (parentcnt) => { using (CEF.NewServiceScope()) { var parent = CEF.NewObject(new PersonWrapped() { Name = $"NP{parentcnt}", Age = (parentcnt % 60) + 20, Gender = (parentcnt % 2) == 0 ? "F" : "M" }); parent.Phones.Add(new Phone() { Number = "888-7777", PhoneTypeID = PhoneType.Mobile }); parent.Phones.Add(new Phone() { Number = "777-6666", PhoneTypeID = PhoneType.Work }); if ((parentcnt % 12) == 0) { CEF.NewObject(new Phone() { Number = "666-5555", PhoneTypeID = PhoneType.Home }); } else { parent.Phones.Add(new Phone() { Number = "777-6666", PhoneTypeID = PhoneType.Home }); } Interlocked.Add(ref cnt1, 4); for (int childcnt = 1; childcnt <= (parentcnt % 4); ++childcnt) { var child = CEF.NewObject(new PersonWrapped() { Name = $"NC{parentcnt}{childcnt}", Age = parent.Age - 20, Gender = (parentcnt % 2) == 0 ? "F" : "M" , Phones = new Phone[] { new Phone() { Number = "999-8888", PhoneTypeID = PhoneType.Mobile } } }); parent.Kids.Add(child); Interlocked.Add(ref cnt1, 2); } CEF.DBSave(); } }); rowcount += (int)cnt1; testTimes.Add(watch.ElapsedMilliseconds); watch.Restart(); long cnt2 = 0; // For purposes of benchmarking, treat this as a completely separate operation // For everyone who's a parent of at least 30 yo, if at least 2 children of same sex, remove work phone, increment age int?id = null; using (var ss = CEF.NewServiceScope()) { var people2 = new EntitySet <Person>().DBRetrieveSummaryForParents(30); Parallel.ForEach((from a in people2 let d = a.AsDynamic() where d.MaleChildren > 1 || d.FemaleChildren > 1 select a).ToList(), (p) => { using (CEF.UseServiceScope(ss)) { if (!id.HasValue) { id = p.PersonID; } p.AsInfraWrapped().SetValue(nameof(Person.Age), p.Age + 1); var ph2 = new EntitySet <Phone>().DBRetrieveByOwner(p.PersonID, PhoneType.Work).FirstOrDefault(); if (ph2 != null) { CEF.DeleteObject(ph2); } p.DBSave(); Interlocked.Add(ref cnt2, 2); } }); // Simulate "later heavy read access"... for (int c = 0; c < 50000; ++c) { var work = new EntitySet <Phone>().DBRetrieveByOwner(c + id.GetValueOrDefault(), PhoneType.Work).FirstOrDefault(); if (work != null && work.Number == "123") { MessageBox.Show("Found (should never!)"); } } } rowcount2 += (int)cnt2 + 50000; watch.Stop(); testTimes2.Add(watch.ElapsedMilliseconds); }
internal static void CopyParsePropertyValues(IDictionary <string, object?>?sourceProps, object target, bool isNew, ServiceScope?ss, IDictionary <object, object> visits, bool justTraverse) { // Can disable this to improve performance - default is enabled if (!Globals.DoCopyParseProperties) { return; } _propCache.TryGetValue(target.GetType(), out var dic); if (dic == null) { dic = (from a in target.FastGetAllProperties(true, true) select new { Name = a.name, PropertyType = a.type }).ToDictionary((p) => p.Name, (p) => p.PropertyType); _propCache[target.GetType()] = dic; } var iter = sourceProps == null ? (from t in dic select(t.Key, target.FastGetValue(t.Key), t.Value)) : (from s in sourceProps from t in dic where s.Key == t.Key select(s.Key, s.Value, t.Value)); var maxdop = Globals.EnableParallelPropertyParsing && Environment.ProcessorCount > 4 && iter.Count() >= Environment.ProcessorCount ? Environment.ProcessorCount >> 2 : 1; Interlocked.Add(ref _copyNesting, maxdop); try { void a((string PropName, object SourceVal, Type TargPropType) info) { object?wrapped = null; if (ss != null && IsWrappableListType(info.TargPropType, info.SourceVal)) { ICEFList?wrappedCol = null; if (ss.Settings.InitializeNullCollections || info.SourceVal != null) { // This by definition represents CHILDREN // Use an observable collection we control - namely EntitySet wrappedCol = CreateWrappingList(ss, info.TargPropType, target, info.PropName); target.FastSetValue(info.PropName, wrappedCol); } else { wrappedCol = info.SourceVal as ICEFList; } // Merge any existing data into the collection - as we do this, recursively construct wrappers! if (info.SourceVal != null && wrappedCol != null) { // Based on the above type checks, we know this thing supports IEnumerable var sValEnum = ((System.Collections.IEnumerable)info.SourceVal).GetEnumerator(); while (sValEnum.MoveNext()) { if (visits.ContainsKey(sValEnum.Current)) { wrapped = visits[sValEnum.Current] ?? sValEnum.Current; } else { wrapped = ss.InternalCreateAddBase(sValEnum.Current, isNew, null, null, null, visits, true, true); } if (wrapped != null) { wrappedCol.AddWrappedItem(wrapped); } } } if (wrappedCol != null && (ss.Settings.InitializeNullCollections || info.SourceVal != null)) { ((ISupportInitializeNotification)wrappedCol).EndInit(); } } else { // If the type is a ref type that we manage, then this property represents a PARENT and we should replace/track it (only if we have a PK for it: without one, can't be tracked) if (ss != null && info.SourceVal != null) { var svt = info.SourceVal.GetType(); if (!_sourceValTypeOk.TryGetValue(svt, out bool svtok)) { svtok = !svt.IsValueType && svt != typeof(string) && KeyService.ResolveKeyDefinitionForType(svt).Any(); _sourceValTypeOk[svt] = svtok; } if (svtok) { if (visits.ContainsKey(info.SourceVal)) { wrapped = visits[info.SourceVal] ?? info.SourceVal; } else { var to = ss.GetTrackedByWrapperOrTarget(info.SourceVal); if (to == null) { wrapped = ss.InternalCreateAddBase(info.SourceVal, isNew, null, null, null, visits, true, true); } else { wrapped = to.GetWrapperTarget(); } } if (wrapped != null) { target.FastSetValue(info.PropName, wrapped); } } else { if (!justTraverse) { target.FastSetValue(info.PropName, info.SourceVal); } } } else { if (!justTraverse) { target.FastSetValue(info.PropName, info.SourceVal); } } } } int resdop = Interlocked.Read(ref _copyNesting) > 12 ? 1 : maxdop; if (resdop == 1) { foreach (var info in iter) { a(info); } } else { ss ??= CEF.CurrentServiceScope; Parallel.ForEach(iter, new ParallelOptions() { MaxDegreeOfParallelism = resdop }, (info) => { using (CEF.UseServiceScope(ss)) { a(info); } }); } } finally { Interlocked.Add(ref _copyNesting, -maxdop); } }
public void AddByQuery <T>(IEnumerable <T> list, string text, object[] parms = null, int?expirySeconds = null, CacheBehavior?mode = null) where T : class, new() { var ss = CEF.CurrentServiceScope; if (mode == null) { mode = ss.ResolvedCacheBehaviorForType(typeof(T)); } if ((mode & CacheBehavior.QueryBased) == 0 && (mode & CacheBehavior.ConvertQueryToIdentity) != 0 && ((mode & CacheBehavior.ForAllDoesntConvertToIdentity) == 0 || string.Compare(text, "All", true) != 0)) { // All we can do is for all list items, add to identity cache void act2() { try { Interlocked.Increment(ref _working); Parallel.ForEach(list, (i) => { using (CEF.UseServiceScope(ss)) { AddByIdentity <T>(i, expirySeconds: expirySeconds); } }); } catch (Exception ex) { CEFDebug.WriteInfo($"Exception in cache serializer: {ex.Message}"); } finally { Interlocked.Decrement(ref _working); } } if (Globals.AsyncCacheUpdates) { Task.Factory.StartNew(act2); } else { act2(); } return; } if ((mode & CacheBehavior.OnlyForAllQuery) != 0 && string.Compare(text, "All", true) != 0) { return; } StringBuilder sb = new StringBuilder(128); sb.Append(typeof(T).Name); sb.Append(text.ToUpperInvariant()); if (parms != null) { foreach (var k in parms) { sb.Append(k); } } string hash; using (SHA256Managed hasher = new SHA256Managed()) { hash = Convert.ToBase64String(hasher.ComputeHash(Encoding.ASCII.GetBytes(sb.ToString()))); } var c = _index.GetFirstByName(nameof(MFSEntry.ByQuerySHA), hash); if (!expirySeconds.HasValue) { expirySeconds = CEF.CurrentServiceScope.ResolvedCacheDurationForType(typeof(T)); } var newExpDate = DateTime.Now.AddSeconds(expirySeconds.GetValueOrDefault(DefaultCacheIntervalSeconds)); if (c == null) { c = new MFSEntry(); if (list.Any()) { c.ObjectTypeName = list.First().GetBaseType().Name; } else { c.ObjectTypeName = typeof(T).Name; } c.ByQuerySHA = hash; c.FileName = BuildNewFileName(typeof(T)); c.QueryForAll = string.Compare(text, "All", true) == 0; _index.Add(c); } long current; lock (c.ObjSync) { current = ++c.Sequence; c.ExpiryDate = newExpDate; c.SourceList = list; c.Active = true; } void act() { try { Interlocked.Increment(ref _working); using (CEF.UseServiceScope(ss)) { // Process all items in parallel, building a list we'll turn into json but also potentially caching "by identity" per row ConcurrentBag <IDictionary <string, object> > rows = new ConcurrentBag <IDictionary <string, object> >(); var aiw = list.AllAsInfraWrapped().ToArray(); Parallel.ForEach(aiw, (iw) => { using (CEF.UseServiceScope(ss)) { rows.Add(iw.GetAllValues(true, true)); if ((mode & CacheBehavior.ConvertQueryToIdentity) != 0 && ((mode & CacheBehavior.ForAllDoesntConvertToIdentity) == 0 || string.Compare(text, "All", true) != 0)) { var uw = iw.AsUnwrapped() as T; if (uw != null) { AddByIdentity <T>(uw, expirySeconds: expirySeconds); } } } }); lock (c.ObjSync) { if (c.Sequence == current) { c.Rows = rows; c.SourceList = null; } } } } catch (Exception ex) { CEFDebug.WriteInfo($"Exception in cache serializer: {ex.Message}"); // Invalidate the entry is probably the safest c.Active = false; c.Properties = null; c.Rows = null; } finally { Interlocked.Decrement(ref _working); } } if (Globals.AsyncCacheUpdates) { Task.Factory.StartNew(act); } else { act(); } }