Dictionary <Lite <RoleEntity>, RoleAllowedCache> NewCache() { using (AuthLogic.Disable()) using (new EntityCache(EntityCacheType.ForceNewSealed)) { List <Lite <RoleEntity> > roles = AuthLogic.RolesInOrder().ToList(); var rules = Database.Query <RuleTypeEntity>().ToList(); var errors = GraphExplorer.FullIntegrityCheck(GraphExplorer.FromRoots(rules)); if (errors != null) { throw new IntegrityCheckException(errors); } Dictionary <Lite <RoleEntity>, Dictionary <Type, TypeAllowedAndConditions> > realRules = rules.AgGroupToDictionary(ru => ru.Role, gr => gr .SelectCatch(ru => KeyValuePair.Create(TypeLogic.EntityToType.GetOrThrow(ru.Resource), ru.ToTypeAllowedAndConditions())) .ToDictionaryEx()); Dictionary <Lite <RoleEntity>, RoleAllowedCache> newRules = new Dictionary <Lite <RoleEntity>, RoleAllowedCache>(); foreach (var role in roles) { var related = AuthLogic.RelatedTo(role); newRules.Add(role, new RoleAllowedCache(role, merger, related.Select(r => newRules.GetOrThrow(r)).ToList(), realRules.TryGetC(role))); } return(newRules); } }
static void Validate <T>(IEnumerable <T> entities) where T : Entity { #if DEBUG var errors = new List <IntegrityCheckWithEntity>(); foreach (var e in entities) { var ic = e.FullIntegrityCheck(); if (ic != null) { var withEntites = ic.WithEntities(GraphExplorer.FromRoots(entities)); errors.AddRange(withEntites); } } if (errors.Count > 0) { throw new IntegrityCheckException(errors); } #else var errors = new Dictionary <Guid, IntegrityCheck>(); foreach (var e in entities) { var ic = e.FullIntegrityCheck(); if (ic != null) { errors.AddRange(ic); } } if (errors.Count > 0) { throw new IntegrityCheckException(errors); } #endif }
private void AssertRetrieved <T>(List <T> list) where T : Modifiable { var graph = GraphExplorer.FromRoots(list); var problematic = graph.Where(a => a.IsGraphModified && a is Entity && (((Entity)a).IdOrNull == null || ((Entity)a).IsNew)); if (problematic.Any()) { Assert.True(false, "Some non-retrived elements: {0}".FormatWith(problematic.ToString(", "))); } }
public void SaveManyMList() { using (var tr = new Transaction()) using (OperationLogic.AllowSave <LabelEntity>()) using (OperationLogic.AllowSave <CountryEntity>()) using (OperationLogic.AllowSave <AlbumEntity>()) using (OperationLogic.AllowSave <ArtistEntity>()) { var prev = Database.MListQuery((AlbumEntity a) => a.Songs).Count(); var authors = Database.Query <BandEntity>().Take(6).ToList().Concat <IAuthorEntity>( Database.Query <ArtistEntity>().Take(8).ToList()).ToList(); var label = new LabelEntity { Name = "Four Music", Country = new CountryEntity { Name = "Germany" }, Node = MusicLoader.NextLabelNode() }; List <AlbumEntity> albums = 0.To(16).Select(i => new AlbumEntity() { Name = "System Greatest hits {0}".FormatWith(i), Author = i < authors.Count ? authors[i] : new ArtistEntity { Name = ".Net Framework" }, Year = 2001, Songs = { new SongEmbedded { Name = "Compilation {0}".FormatWith(i) } }, State = AlbumState.Saved, Label = label, }).ToList(); albums.SaveList(); Assert.All(GraphExplorer.FromRoots(albums), a => Assert.False(a.IsGraphModified)); Assert.Equal(prev + 16, Database.MListQuery((AlbumEntity a) => a.Songs).Count()); albums.ForEach(a => a.Name += "Updated"); albums.SaveList(); albums.ForEach(a => a.Songs.ForEach(s => s.Name = "Updated")); albums.SaveList(); //tr.Commit(); } }
static void Validate <T>(IEnumerable <T> entities) where T : Entity { foreach (var e in entities) { var ic = e.FullIntegrityCheck(); if (ic != null) { #if DEBUG throw new IntegrityCheckException(ic.WithEntities(GraphExplorer.FromRoots(entities))); #else throw new IntegrityCheckException(ic); #endif } } }
public void RetrieveSealed() { using (Transaction tr = new Transaction()) using (new EntityCache(EntityCacheType.ForceNewSealed)) { var albums = Database.Query <AlbumEntity>().ToList(); Assert2.AssertAll(GraphExplorer.FromRoots(albums), a => a.Modified == ModifiedState.Sealed); Assert2.Throws <InvalidOperationException>("sealed", () => albums.First().Name = "New name"); var notes = Database.Query <NoteWithDateEntity>().ToList(); Assert2.AssertAll(GraphExplorer.FromRoots(notes), a => a.Modified == ModifiedState.Sealed); //tr.Commit(); } }
/// <param name="keySelector">Unique key to retrieve ids</param> /// <param name="isNewPredicate">Optional filter to query only the recently inseted entities</param> public static int BulkInsertQueryIds <T, K>(this IEnumerable <T> entities, Expression <Func <T, K> > keySelector, Expression <Func <T, bool> >?isNewPredicate = null, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, bool preSaving = true, bool validateFirst = true, int?timeout = null, string?message = null) where T : Entity where K : notnull { using (HeavyProfiler.Log(nameof(BulkInsertQueryIds), () => typeof(T).TypeName())) using (Transaction tr = new Transaction()) { var t = Schema.Current.Table(typeof(T)); var list = entities.ToList(); if (isNewPredicate == null) { isNewPredicate = GetFilterAutomatic <T>(t); } var rowNum = BulkInsertTable <T>(list, copyOptions, preSaving, validateFirst, false, timeout, message); var dictionary = Database.Query <T>().Where(isNewPredicate).Select(a => KeyValuePair.Create(keySelector.Evaluate(a), a.Id)).ToDictionaryEx(); var getKeyFunc = keySelector.Compile(); list.ForEach(e => { e.SetId(dictionary.GetOrThrow(getKeyFunc(e))); e.SetIsNew(false); }); BulkInsertMLists(list, copyOptions, timeout, message); GraphExplorer.CleanModifications(GraphExplorer.FromRoots(list)); return(tr.Commit(rowNum)); } }
public void SaveManyMList() { using (Transaction tr = new Transaction()) using (OperationLogic.AllowSave <AlbumEntity>()) using (OperationLogic.AllowSave <ArtistEntity>()) { var prev = Database.MListQuery((AlbumEntity a) => a.Songs).Count(); var authors = Database.Query <BandEntity>().Take(6).ToList().Concat <IAuthorEntity>( Database.Query <ArtistEntity>().Take(8).ToList()).ToList(); List <AlbumEntity> albums = 0.To(16).Select(i => new AlbumEntity() { Name = "System Greatest hits {0}".FormatWith(i), Author = i < authors.Count ? authors[i] : new ArtistEntity { Name = ".Net Framework" }, Year = 2001, Songs = { new SongEntity { Name = "Compilation {0}".FormatWith(i) } }, State = AlbumState.Saved }).ToList(); albums.SaveList(); Assert2.AssertAll(GraphExplorer.FromRoots(albums), a => !a.IsGraphModified); Assert.AreEqual(prev + 16, Database.MListQuery((AlbumEntity a) => a.Songs).Count()); albums.ForEach(a => a.Name += "Updated"); albums.SaveList(); albums.ForEach(a => a.Songs.ForEach(s => s.Name = "Updated")); albums.SaveList(); //tr.Commit(); } }
public static int BulkInsertTable <T>(IEnumerable <T> entities, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, bool preSaving = true, bool validateFirst = true, bool disableIdentity = false, int?timeout = null, string?message = null) where T : Entity { using (HeavyProfiler.Log(nameof(BulkInsertTable), () => typeof(T).TypeName())) { if (message != null) { return(SafeConsole.WaitRows(message == "auto" ? $"BulkInsering {entities.Count()} {typeof(T).TypeName()}" : message, () => BulkInsertTable(entities, copyOptions, preSaving, validateFirst, disableIdentity, timeout, message: null))); } if (disableIdentity) { copyOptions |= SqlBulkCopyOptions.KeepIdentity; } if (copyOptions.HasFlag(SqlBulkCopyOptions.UseInternalTransaction)) { throw new InvalidOperationException("BulkInsertDisableIdentity not compatible with UseInternalTransaction"); } var list = entities.ToList(); if (preSaving) { Saver.PreSaving(() => GraphExplorer.FromRoots(list)); } if (validateFirst) { Validate <T>(list); } var t = Schema.Current.Table <T>(); bool disableIdentityBehaviour = copyOptions.HasFlag(SqlBulkCopyOptions.KeepIdentity); DataTable dt = new DataTable(); var columns = t.Columns.Values.Where(c => !(c is SystemVersionedInfo.SqlServerPeriodColumn) && (disableIdentityBehaviour || !c.IdentityBehaviour)).ToList(); foreach (var c in columns) { dt.Columns.Add(new DataColumn(c.Name, ConvertType(c.Type))); } using (disableIdentityBehaviour ? Administrator.DisableIdentity(t, behaviourOnly: true) : null) { foreach (var e in list) { if (!e.IsNew) { throw new InvalidOperationException("Entites should be new"); } t.SetToStrField(e); dt.Rows.Add(t.BulkInsertDataRow(e)); } } using (Transaction tr = new Transaction()) { Schema.Current.OnPreBulkInsert(typeof(T), inMListTable: false); Executor.BulkCopy(dt, columns, t.Name, copyOptions, timeout); foreach (var item in list) { item.SetNotModified(); } return(tr.Commit(list.Count)); } } }
public static void Save(Entity[] entities) { if (entities == null || entities.Any(e => e == null)) { throw new ArgumentNullException("entity"); } using (var log = HeavyProfiler.LogNoStackTrace("PreSaving")) { Schema schema = Schema.Current; DirectedGraph <Modifiable> modifiables = PreSaving(() => GraphExplorer.FromRoots(entities)); HashSet <Entity> wasNew = modifiables.OfType <Entity>().Where(a => a.IsNew).ToHashSet(ReferenceEqualityComparer <Entity> .Default); HashSet <Entity> wasSelfModified = modifiables.OfType <Entity>().Where(a => a.Modified == ModifiedState.SelfModified).ToHashSet(ReferenceEqualityComparer <Entity> .Default); log.Switch("Integrity"); var error = GraphExplorer.FullIntegrityCheck(modifiables); if (error != null) { #if DEBUG throw new IntegrityCheckException(error.WithEntities(modifiables)); #else throw new IntegrityCheckException(error); #endif } log.Switch("Graph"); GraphExplorer.PropagateModifications(modifiables.Inverse()); //colapsa modifiables (collections and embeddeds) keeping indentifiables only DirectedGraph <Entity> identifiables = GraphExplorer.ColapseIdentifiables(modifiables); foreach (var node in identifiables) { schema.OnSaving(node); } //Remove all the edges that doesn't mean a dependency identifiables.RemoveEdges(identifiables.Edges.Where(e => !e.To.IsNew).ToList()); //Remove all the nodes that are not modified List <Entity> notModified = identifiables.Where(node => !node.IsGraphModified).ToList(); notModified.ForEach(node => identifiables.RemoveFullNode(node, None)); log.Switch("SaveGroups"); SaveGraph(schema, identifiables); foreach (var node in identifiables) { schema.OnSaved(node, new SavedEventArgs { IsRoot = entities.Contains(node), WasNew = wasNew.Contains(node), WasSelfModified = wasSelfModified.Contains(node), }); } EntityCache.Add(identifiables); EntityCache.Add(notModified); GraphExplorer.CleanModifications(modifiables); } }
public static int BulkInsertTable <T>(IEnumerable <T> entities, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, bool preSaving = false, bool validateFirst = false, bool disableIdentity = false, int?timeout = null, string message = null) where T : Entity { if (message != null) { return(SafeConsole.WaitRows(message == "auto" ? $"BulkInsering {entities.Count()} {typeof(T).TypeName()}" : message, () => BulkInsertTable(entities, copyOptions, preSaving, validateFirst, disableIdentity, timeout, message: null))); } if (disableIdentity) { copyOptions |= SqlBulkCopyOptions.KeepIdentity; } if (copyOptions.HasFlag(SqlBulkCopyOptions.UseInternalTransaction)) { throw new InvalidOperationException("BulkInsertDisableIdentity not compatible with UseInternalTransaction"); } var list = entities.ToList(); if (preSaving) { Schema schema = Schema.Current; GraphExplorer.PreSaving(() => GraphExplorer.FromRoots(list), (Modifiable m, ref bool graphModified) => { if (m is ModifiableEntity me) { me.SetTemporalErrors(null); } m.PreSaving(ref graphModified); if (m is Entity ident) { schema.OnPreSaving(ident, ref graphModified); } }); } if (validateFirst) { Validate <T>(list); } var t = Schema.Current.Table <T>(); bool disableIdentityBehaviour = copyOptions.HasFlag(SqlBulkCopyOptions.KeepIdentity); bool oldIdentityBehaviour = t.IdentityBehaviour; DataTable dt = new DataTable(); foreach (var c in disableIdentityBehaviour ? t.Columns.Values : t.Columns.Values.Where(c => !c.IdentityBehaviour)) { dt.Columns.Add(new DataColumn(c.Name, c.Type.UnNullify())); } if (disableIdentityBehaviour) { t.IdentityBehaviour = false; } foreach (var e in entities) { if (!e.IsNew) { throw new InvalidOperationException("Entites should be new"); } t.SetToStrField(e); dt.Rows.Add(t.BulkInsertDataRow(e)); } if (disableIdentityBehaviour) { t.IdentityBehaviour = oldIdentityBehaviour; } using (Transaction tr = new Transaction()) { Schema.Current.OnPreBulkInsert(typeof(T), inMListTable: false); Executor.BulkCopy(dt, t.Name, copyOptions, timeout); foreach (var item in list) { item.SetNotModified(); } return(tr.Commit(list.Count)); } }