public void InitializeNonparsableProperties(out IEnumerable<IConceptInfo> createdConcepts) { if (!(Property.DataStructure is EntityInfo)) throw new DslSyntaxException(this, "History concept may only be used on entity or its property."); Dependency_EntityHistory = new EntityHistoryInfo { Entity = (EntityInfo)this.Property.DataStructure }; createdConcepts = new IConceptInfo[] { Dependency_EntityHistory }; }
private static string CreateHistoryOnUpdateSnippet(EntityHistoryInfo info) { return string.Format( @" if (insertedNew.Count() > 0 || updatedNew.Count() > 0) {{ var now = SqlUtility.GetDatabaseTime(_executionContext.SqlExecuter); const double errorMarginSeconds = 0.01; // Including database DataTime type imprecision. foreach (var newItem in insertedNew.Concat(updatedNew)) if (newItem.ActiveSince == null) newItem.ActiveSince = now; if (updatedNew.Count() > 0 && !(updatedNew is Common.DontTrackHistory<{0}.{1}>)) {{ var createHistory = updatedNew.Zip(updated, (newItem, oldItem) => new {{ newItem, oldItem }}) .Where(change => (change.oldItem.ActiveSince == null || change.newItem.ActiveSince > change.oldItem.ActiveSince.Value.AddSeconds(errorMarginSeconds))) .Select(change => change.oldItem) .ToArray(); _domRepository.{0}.{1}_Changes.Insert( createHistory.Select(olditem => new {0}.{1}_Changes {{ ID = Guid.NewGuid(), EntityID = olditem.ID{2} }}).ToArray()); }} }} ", info.Entity.Module.Name, info.Entity.Name, ClonePropertiesTag.Evaluate(info)); }
/// <summary> /// Additional parameter _createChangesEntryOnEdit. It is used in History update. /// If active item is edited through history, it should not create new entry in Changes table. /// </summary> private static string AdditionalParameterSnippet(EntityHistoryInfo info) { return @" private bool _overwriteCurrentRecordOnUpdate; public virtual void SetOverwriteCurrentRecordOnUpdate(bool value) { this._overwriteCurrentRecordOnUpdate = value; } public virtual bool GetOverwriteCurrentRecordOnUpdate() { return this._overwriteCurrentRecordOnUpdate; } "; }
public void InitializeNonparsableProperties(out IEnumerable <IConceptInfo> createdConcepts) { if (!(Property.DataStructure is EntityInfo)) { throw new DslSyntaxException(this, "History concept may only be used on entity or its property."); } Dependency_EntityHistory = new EntityHistoryInfo { Entity = (EntityInfo)this.Property.DataStructure }; createdConcepts = new IConceptInfo[] { Dependency_EntityHistory }; }
/// <summary> /// Creates a DateTime filter that returns the "Entity"_Changes records that were active at the time (including the current records in the base entity). /// AllProperties concept (EntityHistoryAllPropertiesInfo) creates a similar filter on the base Entity class. /// </summary> private static string FilterImplementationSnippet(EntityHistoryInfo info) { return string.Format( @" public global::{0}.{1}[] Filter(System.DateTime parameter) {{ var sql = ""SELECT * FROM {2}.{3}(@p0)""; var query = _executionContext.EntityFrameworkContext.Database.SqlQuery<{0}.{1}>(sql, parameter); return query.ToArray(); }} ", info.Dependency_ChangesEntity.Module.Name, info.Dependency_ChangesEntity.Name, SqlUtility.Identifier(info.Entity.Module.Name), SqlUtility.Identifier(info.Entity.Name + "_AtTime")); }
private static string CreateHistoryOnUpdateSnippet(EntityHistoryInfo info) { return string.Format( @" if (insertedNew.Count() > 0 || updatedNew.Count() > 0) {{ var now = SqlUtility.GetDatabaseTime(_executionContext.SqlExecuter); const double errorMarginSeconds = 0.01; // Including database DataTime type imprecision. foreach (var newItem in insertedNew.Concat(updatedNew)) if (newItem.ActiveSince == null) newItem.ActiveSince = now; else if (newItem.ActiveSince > now.AddSeconds(errorMarginSeconds)) throw new Rhetos.UserException(string.Format( ""It is not allowed to enter a future time in {0}.{1}.ActiveSince ({{0}}). Set the property value to NULL to automatically use current time ({{1}})."", newItem.ActiveSince, now)); if (updatedNew.Count() > 0) {{ var createHistory = updatedNew.Zip(updated, (newItem, oldItem) => new {{ newItem, oldItem }}) .Where(change => (change.oldItem.ActiveSince == null || change.newItem.ActiveSince > change.oldItem.ActiveSince.Value.AddSeconds(errorMarginSeconds)) && !change.newItem.GetOverwriteCurrentRecordOnUpdate()) .Select(change => change.oldItem) .ToArray(); _domRepository.{0}.{1}_Changes.Insert( createHistory.Select(olditem => new {0}.{1}_Changes {{ ID = Guid.NewGuid(), EntityID = olditem.ID{2} }}).ToArray()); }} // Workaround to restore NH proxies if NHSession.Clear() is called inside filter. for (int i=0; i<updated.Length; i++) updated[i] = _executionContext.NHibernateSession.Load<{0}.{1}>(updated[i].ID); for (int i=0; i<deleted.Length; i++) deleted[i] = _executionContext.NHibernateSession.Load<{0}.{1}>(deleted[i].ID); }} ", info.Entity.Module.Name, info.Entity.Name, ClonePropertiesTag.Evaluate(info)); }
public void InitializeNonparsableProperties(out IEnumerable <IConceptInfo> createdConcepts) { if (!(Property.DataStructure is EntityInfo)) { throw new DslSyntaxException(this, "History concept may only be used on entity or its property."); } Dependency_EntityHistory = new EntityHistoryInfo { Entity = (EntityInfo)Property.DataStructure }; Dependency_AtTimeSqlFunction = new SqlFunctionInfo { Module = Property.DataStructure.Module, Name = Property.DataStructure.Name + "_AtTime" }; Dependency_HistorySqlQueryable = new SqlQueryableInfo { Module = Property.DataStructure.Module, Name = Property.DataStructure.Name + "_History" }; Dependency_Write = new WriteInfo { DataStructure = Dependency_HistorySqlQueryable }; createdConcepts = new IConceptInfo[] { Dependency_EntityHistory }; }
private static string VerifyChangesEntityTimeSnippet(EntityHistoryInfo info) { return string.Format( @" if (insertedNew.Count() > 0 || updatedNew.Count() > 0) {{ var now = SqlUtility.GetDatabaseTime(_executionContext.SqlExecuter); foreach (var newItem in insertedNew.Concat(updatedNew)) if (newItem.ActiveSince > now) throw new Rhetos.UserException(string.Format( ""It is not allowed to enter a future time in {0}.{1}.ActiveSince ({{0}}). Current server time is {{1}}."", newItem.ActiveSince, now)); }} ", info.ChangesEntity.Module.Name, info.ChangesEntity.Name); }
private static string FilterInterfaceSnippet(EntityHistoryInfo info) { return "IFilterRepository<System.DateTime, " + info.ChangesEntity.Module.Name + "." + info.ChangesEntity.Name + ">"; }
/// <summary> /// Creates a DateTime filter that returns the "Entity"_Changes records that were active at the time (including the current records in the base entity). /// AllProperties concept (EntityHistoryAllPropertiesInfo) creates a similar filter on the base Entity class. /// </summary> private static string FilterImplementationSnippet(EntityHistoryInfo info) { return string.Format( @" public global::{0}.{1}[] Filter(System.DateTime parameter) {{ var sql = ""SELECT * FROM {2}.{3}(:dateTime)""; var result = _executionContext.NHibernateSession.CreateSQLQuery(sql) .AddEntity(typeof({0}.{1})) .SetTimestamp(""dateTime"", parameter) .List<{0}.{1}>(); return result.ToArray(); }} ", info.ChangesEntity.Module.Name, info.ChangesEntity.Name, SqlUtility.Identifier(info.Entity.Module.Name), SqlUtility.Identifier(info.Entity.Name + "_AtTime")); }