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; }
     ";
 }
Beispiel #4
0
 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));
        }
Beispiel #7
0
        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"));
        }