private static string ReferenceIDSnippet(ReferencePropertyInfo info, PropertyInfo referenceGuid) { return string.Format( @" {3} public virtual Guid? {0}ID {{ get {{ if ({0} != null) return {0}.ID; return null; }} set {{ if(value == null) {0} = null; else {0} = new {1}.{2} {{ ID = value.Value }}; }} }} ", info.Name, info.Referenced.Module.Name, info.Referenced.Name, PropertyHelper.AttributeTag.Evaluate(referenceGuid)); }
public static string GetConstraintName(ReferencePropertyInfo info) { return SqlUtility.Identifier(Sql.Format("ReferencePropertyConstraintDatabaseDefinition_ConstraintName", info.DataStructure.Name, info.Referenced.Name, info.Name)); }
// NH does not allow both Guid and navigation properties to be mapped to the same table column, unless one of the properties is not writable (insert and update mapping set to "false"). // If the Guid property was defined *after* the navigation property in the .xml mapping file, the lazy loading of the reference would not work. private string SnippetMapping(ReferencePropertyInfo info) { return string.Format( @" <many-to-one {2} class=""{0}.{1}, " + NHibernateMappingGenerator.AssemblyTag + @""" {3} /> <property {4} update=""false"" insert=""false"" /> ", info.Referenced.Module.Name, info.Referenced.Name, NhUtility.PropertyAndColumnNameMapping(info.Name, info.Name + "ID"), string.Format(MappingTag, info.DataStructure.Module.Name, info.DataStructure.Name, info.Name), NhUtility.PropertyAndColumnNameMapping(info.Name + "ID")); }
private static string CodeSnippetDeleteChildren(ReferencePropertyInfo reference) { return string.Format( @" if (deleted.Count() > 0) {{ {0}.{1}[] childItems = deleted.SelectMany(parent => _executionContext.NHibernateSession.Query<{0}.{1}>().Where(child => child.{2}.ID == parent.ID).ToArray()).ToArray(); if (childItems.Count() > 0) _domRepository.{0}.{1}.Delete(childItems); }} ", reference.DataStructure.Module.Name, reference.DataStructure.Name, reference.Name); }
public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts) { var newConcepts = new List <IConceptInfo>(); // Expand the base entity: var activeSinceProperty = new DateTimePropertyInfo { DataStructure = Entity, Name = "ActiveSince" }; // TODO: SystemRequired, Default 1.1.1900. var activeSinceHistory = new EntityHistoryPropertyInfo { Property = activeSinceProperty }; newConcepts.AddRange(new IConceptInfo[] { activeSinceProperty, activeSinceHistory }); // InvalidData for base entity: it is not allowed to save with ActiveSince older than last one used in History var denyFilter = new ComposableFilterByInfo { Parameter = "Common.OlderThanHistoryEntries", Source = Entity, Expression = String.Format( @"(items, repository, parameter) => items.Where(item => repository.{0}.{1}_Changes.Subquery.Where(his => his.ActiveSince >= item.ActiveSince && his.Entity == item).Count() > 0)", Entity.Module.Name, Entity.Name) }; var invalidDataValidation = new InvalidDataMarkPropertyInfo { FilterType = "Common.OlderThanHistoryEntries", Source = Entity, ErrorMessage = "ActiveSince is not allowed to be older than last entry in history.", DependedProperty = activeSinceProperty }; newConcepts.AddRange(new IConceptInfo[] { denyFilter, invalidDataValidation, new ParameterInfo { Module = new ModuleInfo { Name = "Common" }, Name = "OlderThanHistoryEntries" } }); // Create a new entity for history data: var currentProperty = new ReferencePropertyInfo { DataStructure = Dependency_ChangesEntity, Name = "Entity", Referenced = Entity }; var historyActiveSinceProperty = new DateTimePropertyInfo { DataStructure = Dependency_ChangesEntity, Name = activeSinceProperty.Name }; newConcepts.AddRange(new IConceptInfo[] { currentProperty, new ReferenceDetailInfo { Reference = currentProperty }, new RequiredPropertyInfo { Property = currentProperty }, // TODO: SystemRequired new PropertyFromInfo { Destination = Dependency_ChangesEntity, Source = activeSinceProperty }, historyActiveSinceProperty, new UniquePropertiesInfo { DataStructure = Dependency_ChangesEntity, Property1 = currentProperty, Property2 = historyActiveSinceProperty } }); // InvalidData for history entity: it is not allowed to save with ActiveSince newer than current entity var denyFilterHistory = new ComposableFilterByInfo { Parameter = "Common.NewerThanCurrentEntry", Source = Dependency_ChangesEntity, Expression = @"(items, repository, parameter) => items.Where(item => item.ActiveSince > item.Entity.ActiveSince)" }; var invalidDataValidationHistory = new InvalidDataMarkPropertyInfo { FilterType = "Common.NewerThanCurrentEntry", Source = Dependency_ChangesEntity, ErrorMessage = "ActiveSince of history entry is not allowed to be newer than current entry.", DependedProperty = historyActiveSinceProperty }; newConcepts.AddRange(new IConceptInfo[] { denyFilterHistory, invalidDataValidationHistory, new ParameterInfo { Module = new ModuleInfo { Name = "Common" }, Name = "NewerThanCurrentEntry" } }); // Create ActiveUntil SqlQueryable: var activeUntilSqlQueryable = new SqlQueryableInfo { Module = Entity.Module, Name = Entity.Name + "_ChangesActiveUntil", SqlSource = ActiveUntilSqlSnippet() }; newConcepts.AddRange(new IConceptInfo[] { activeUntilSqlQueryable, new DateTimePropertyInfo { DataStructure = activeUntilSqlQueryable, Name = "ActiveUntil" }, new SqlDependsOnDataStructureInfo { Dependent = activeUntilSqlQueryable, DependsOn = Dependency_ChangesEntity }, new SqlDependsOnDataStructureInfo { Dependent = activeUntilSqlQueryable, DependsOn = Entity }, new DataStructureExtendsInfo { Base = Dependency_ChangesEntity, Extension = activeUntilSqlQueryable } }); // Configure History SqlQueryable: newConcepts.AddRange(new IConceptInfo[] { new SqlDependsOnDataStructureInfo { Dependent = Dependency_HistorySqlQueryable, DependsOn = Entity }, new SqlDependsOnDataStructureInfo { Dependent = Dependency_HistorySqlQueryable, DependsOn = Dependency_ChangesEntity }, new SqlDependsOnDataStructureInfo { Dependent = Dependency_HistorySqlQueryable, DependsOn = activeUntilSqlQueryable }, new DateTimePropertyInfo { DataStructure = Dependency_HistorySqlQueryable, Name = "ActiveUntil" }, new AllPropertiesFromInfo { Source = Dependency_ChangesEntity, Destination = Dependency_HistorySqlQueryable } }); // Configure AtTime SqlFunction: newConcepts.Add(new SqlDependsOnDataStructureInfo { Dependent = Dependency_AtTimeSqlFunction, DependsOn = Dependency_HistorySqlQueryable }); return(newConcepts); }
public IEnumerable<IConceptInfo> CreateNewConcepts(IEnumerable<IConceptInfo> existingConcepts) { var newConcepts = new List<IConceptInfo>(); // Expand the base entity: var activeSinceProperty = new DateTimePropertyInfo { DataStructure = Entity, Name = "ActiveSince" }; // TODO: SystemRequired, Default 1.1.1900. var activeSinceHistory = new EntityHistoryPropertyInfo { Property = activeSinceProperty }; newConcepts.AddRange(new IConceptInfo[] { activeSinceProperty, activeSinceHistory }); // InvalidData for base entity: it is not allowed to save with ActiveSince older than last one used in History var denyFilter = new ComposableFilterByInfo { Parameter = "Common.OlderThanHistoryEntries", Source = Entity, Expression = String.Format( @"(items, repository, parameter) => items.Where(item => repository.{0}.{1}_Changes.Subquery.Where(his => his.ActiveSince >= item.ActiveSince && his.Entity == item).Count() > 0)", Entity.Module.Name, Entity.Name) }; var invalidDataValidation = new InvalidDataMarkPropertyInfo { FilterType = "Common.OlderThanHistoryEntries", Source = Entity, ErrorMessage = "ActiveSince is not allowed to be older than last entry in history.", DependedProperty = activeSinceProperty }; newConcepts.AddRange(new IConceptInfo[] { denyFilter, invalidDataValidation, new ParameterInfo { Module = new ModuleInfo { Name = "Common" }, Name = "OlderThanHistoryEntries" } }); // Create a new entity for history data: var currentProperty = new ReferencePropertyInfo { DataStructure = Dependency_ChangesEntity, Name = "Entity", Referenced = Entity }; var historyActiveSinceProperty = new DateTimePropertyInfo { DataStructure = Dependency_ChangesEntity, Name = activeSinceProperty.Name }; newConcepts.AddRange(new IConceptInfo[] { currentProperty, new ReferenceDetailInfo { Reference = currentProperty }, new RequiredPropertyInfo { Property = currentProperty }, // TODO: SystemRequired new PropertyFromInfo { Destination = Dependency_ChangesEntity, Source = activeSinceProperty }, historyActiveSinceProperty, new UniquePropertiesInfo { DataStructure = Dependency_ChangesEntity, Property1 = currentProperty, Property2 = historyActiveSinceProperty } }); // InvalidData for history entity: it is not allowed to save with ActiveSince newer than current entity var denyFilterHistory = new ComposableFilterByInfo { Parameter = "Common.NewerThanCurrentEntry", Source = Dependency_ChangesEntity, Expression = @"(items, repository, parameter) => items.Where(item => item.ActiveSince > item.Entity.ActiveSince)" }; var invalidDataValidationHistory = new InvalidDataMarkPropertyInfo { FilterType = "Common.NewerThanCurrentEntry", Source = Dependency_ChangesEntity, ErrorMessage = "ActiveSince of history entry is not allowed to be newer than current entry.", DependedProperty = historyActiveSinceProperty }; newConcepts.AddRange(new IConceptInfo[] { denyFilterHistory, invalidDataValidationHistory, new ParameterInfo { Module = new ModuleInfo { Name = "Common" }, Name = "NewerThanCurrentEntry" } }); // Create ActiveUntil SqlQueryable: var activeUntilSqlQueryable = new SqlQueryableInfo { Module = Entity.Module, Name = Entity.Name + "_ChangesActiveUntil", SqlSource = ActiveUntilSqlSnippet() }; newConcepts.AddRange(new IConceptInfo[] { activeUntilSqlQueryable, new DateTimePropertyInfo { DataStructure = activeUntilSqlQueryable, Name = "ActiveUntil" }, new SqlDependsOnDataStructureInfo { Dependent = activeUntilSqlQueryable, DependsOn = Dependency_ChangesEntity }, new SqlDependsOnDataStructureInfo { Dependent = activeUntilSqlQueryable, DependsOn = Entity }, new DataStructureExtendsInfo { Base = Dependency_ChangesEntity, Extension = activeUntilSqlQueryable } }); // Configure History SqlQueryable: newConcepts.AddRange(new IConceptInfo[] { new SqlDependsOnDataStructureInfo { Dependent = Dependency_HistorySqlQueryable, DependsOn = Entity }, new SqlDependsOnDataStructureInfo { Dependent = Dependency_HistorySqlQueryable, DependsOn = Dependency_ChangesEntity }, new SqlDependsOnDataStructureInfo { Dependent = Dependency_HistorySqlQueryable, DependsOn = activeUntilSqlQueryable }, new DateTimePropertyInfo { DataStructure = Dependency_HistorySqlQueryable, Name = "ActiveUntil" }, new AllPropertiesFromInfo { Source = Dependency_ChangesEntity, Destination = Dependency_HistorySqlQueryable } }); // Configure AtTime SqlFunction: newConcepts.Add(new SqlDependsOnDataStructureInfo { Dependent = Dependency_AtTimeSqlFunction, DependsOn = Dependency_HistorySqlQueryable }); return newConcepts; }
public static bool IsSupported(ReferencePropertyInfo reference) { return(reference.DataStructure is EntityInfo && ForeignKeyUtility.GetSchemaTableForForeignKey(reference.Referenced) != null); }
private static IEnumerable<PropertyInfo> GetReferenceProperties(IEnumerable<IConceptInfo> existingConcepts, ReferencePropertyInfo property) { return existingConcepts.OfType<LookupVisibleInfo>() .Where(r => r.Property.DataStructure == property.Referenced).ToList() .Select(r => r.Property); }
public IEnumerable <IConceptInfo> CreateNewConcepts(IsSubtypeOfInfo conceptInfo, IDslModel existingConcepts) { var newConcepts = new List <IConceptInfo>(); // Add a subtype reference (for each subtype) to the supertype data structure: var subtypeReference = new ReferencePropertyInfo { DataStructure = conceptInfo.Supertype, Referenced = conceptInfo.Subtype, Name = conceptInfo.GetSubtypeReferenceName() }; newConcepts.Add(subtypeReference); newConcepts.Add(new PolymorphicPropertyInfo { Property = subtypeReference, SubtypeReference = conceptInfo.Subtype.GetKeyProperties() }); // Append subtype implementation to the supertype union: newConcepts.Add(new SubtypeExtendPolymorphicInfo { IsSubtypeOf = conceptInfo, SubtypeImplementationView = conceptInfo.GetImplementationViewPrototype(), PolymorphicUnionView = conceptInfo.Supertype.GetUnionViewPrototype() }); var filterBySubtypePrototype = new FilterByInfo { Source = conceptInfo.Supertype, Parameter = "Rhetos.Dom.DefaultConcepts.FilterSubtype" }; newConcepts.Add(new SubtypeExtendFilterInfo { IsSubtypeOf = conceptInfo, FilterBySubtype = filterBySubtypePrototype }); // Add metadata for supertype computation (union): string hashId = conceptInfo.ImplementationName == "" ? "item.ID" : "DomUtility.GetSubtypeImplementationId(item.ID, " + DomUtility.GetSubtypeImplementationHash(conceptInfo.ImplementationName) + ")"; foreach (DataStructureInfo dependsOn in DslUtility.GetBaseChangesOnDependency(conceptInfo.Subtype, existingConcepts)) { newConcepts.Add(new ChangesOnChangedItemsInfo { Computation = conceptInfo.Supertype, DependsOn = dependsOn, FilterType = "Rhetos.Dom.DefaultConcepts.FilterSubtype", FilterFormula = @"changedItems => new Rhetos.Dom.DefaultConcepts.FilterSubtype { Ids = changedItems.Select(item => " + hashId + @").ToArray(), Subtype = " + CsUtility.QuotedString(conceptInfo.Subtype.Module.Name + "." + conceptInfo.Subtype.Name) + @", ImplementationName = " + CsUtility.QuotedString(conceptInfo.ImplementationName) + @" }" }); } // Add metadata for subtype implementation: PersistedSubtypeImplementationIdInfo subtypeImplementationColumn = null; if (conceptInfo.SupportsPersistedSubtypeImplementationColum()) { subtypeImplementationColumn = new PersistedSubtypeImplementationIdInfo { Subtype = conceptInfo.Subtype, ImplementationName = conceptInfo.ImplementationName }; newConcepts.Add(subtypeImplementationColumn); } // Automatic interface implementation: var implementationView = (SqlViewInfo)existingConcepts.FindByKey(conceptInfo.GetImplementationViewPrototype().GetKey()); if (implementationView == null) { implementationView = new ExtensibleSubtypeSqlViewInfo { IsSubtypeOf = conceptInfo }; newConcepts.Add(implementationView); if (subtypeImplementationColumn != null) { newConcepts.Add(new SqlDependsOnSqlObjectInfo { // The subtype implementation view will use the PersistedSubtypeImplementationColumn. DependsOn = subtypeImplementationColumn.GetSqlObjectPrototype(), Dependent = implementationView }); } } // Redirect the developer-provided SQL dependencies from the "Is" concept to the implementation view: newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnDataStructureInfo>(dep => dep.Dependent, conceptInfo) .Select(dep => new SqlDependsOnDataStructureInfo { Dependent = implementationView, DependsOn = dep.DependsOn })); newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnModuleInfo>(dep => dep.Dependent, conceptInfo) .Select(dep => new SqlDependsOnModuleInfo { Dependent = implementationView, DependsOn = dep.DependsOn })); newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnPropertyInfo>(dep => dep.Dependent, conceptInfo) .Select(dep => new SqlDependsOnPropertyInfo { Dependent = implementationView, DependsOn = dep.DependsOn })); newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlFunctionInfo>(dep => dep.Dependent, conceptInfo) .Select(dep => new SqlDependsOnSqlFunctionInfo { Dependent = implementationView, DependsOn = dep.DependsOn })); newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlIndexInfo>(dep => dep.Dependent, conceptInfo) .Select(dep => new SqlDependsOnSqlIndexInfo { Dependent = implementationView, DependsOn = dep.DependsOn })); newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlObjectInfo>(dep => dep.Dependent, conceptInfo) .Select(dep => new SqlDependsOnSqlObjectInfo { Dependent = implementationView, DependsOn = dep.DependsOn })); newConcepts.AddRange(existingConcepts.FindByReference <SqlDependsOnSqlViewInfo>(dep => dep.Dependent, conceptInfo) .Select(dep => new SqlDependsOnSqlViewInfo { Dependent = implementationView, DependsOn = dep.DependsOn })); return(newConcepts); }
public static bool IsSupported(ReferencePropertyInfo info) { return info.DataStructure is EntityInfo; }
public static bool IsSupported(ReferencePropertyInfo info) { return ReferencePropertyDatabaseDefinition.IsSupported(info) && ForeignKeyUtility.GetSchemaTableForForeignKey(info.Referenced) != null; }
public IEnumerable <IConceptInfo> CreateNewConcepts(EntityHistoryInfo conceptInfo, IDslModel existingConcepts) { var newConcepts = new List <IConceptInfo>(); var atTimeSqlFunction = new SqlFunctionInfo { Module = conceptInfo.Entity.Module, Name = conceptInfo.Entity.Name + "_AtTime", Arguments = $"@ContextTime {_dateTimeSqlColumnType}", Source = AtTimeSqlSnippet(conceptInfo) }; newConcepts.Add(atTimeSqlFunction); var historySqlQueryable = new SqlQueryableInfo { Module = conceptInfo.Entity.Module, Name = conceptInfo.Entity.Name + "_History", SqlSource = HistorySqlSnippet(conceptInfo) }; newConcepts.Add(historySqlQueryable); var write = new WriteInfo { DataStructure = historySqlQueryable, SaveImplementation = HistorySaveFunction(conceptInfo) }; newConcepts.Add(write); // Expand the base entity: var activeSinceProperty = new DateTimePropertyInfo { DataStructure = conceptInfo.Entity, Name = "ActiveSince" }; // TODO: SystemRequired, Default 1.1.1900., after implementing optimization for multiple simple property validations. var activeSinceHistory = new EntityHistoryPropertyInfo { Property = activeSinceProperty }; newConcepts.AddRange(new IConceptInfo[] { activeSinceProperty, activeSinceHistory }); // InvalidData for base entity: it is not allowed to save with ActiveSince older than last one used in History var denyFilter = new QueryFilterExpressionInfo { Parameter = "Common.OlderThanHistoryEntries", Source = conceptInfo.Entity, Expression = String.Format( @"(items, parameter) => items.Where(item => _domRepository.{0}.{1}_Changes.Subquery.Where(his => his.ActiveSince >= item.ActiveSince && his.Entity == item).Count() > 0)", conceptInfo.Entity.Module.Name, conceptInfo.Entity.Name) }; var invalidDataValidation = new InvalidDataInfo { FilterType = "Common.OlderThanHistoryEntries", Source = conceptInfo.Entity, ErrorMessage = "ActiveSince is not allowed to be older than last entry in history." }; newConcepts.AddRange(new IConceptInfo[] { denyFilter, invalidDataValidation, new ParameterInfo { Module = new ModuleInfo { Name = "Common" }, Name = "OlderThanHistoryEntries" }, new InvalidDataMarkProperty2Info { InvalidData = invalidDataValidation, MarkProperty = activeSinceProperty } }); // Create a new entity for history data: var currentProperty = new ReferencePropertyInfo { DataStructure = conceptInfo.Dependency_ChangesEntity, Name = "Entity", Referenced = conceptInfo.Entity }; var historyActiveSinceProperty = new DateTimePropertyInfo { DataStructure = conceptInfo.Dependency_ChangesEntity, Name = activeSinceProperty.Name }; newConcepts.AddRange(new IConceptInfo[] { currentProperty, new ReferenceDetailInfo { Reference = currentProperty }, new RequiredPropertyInfo { Property = currentProperty }, // TODO: SystemRequired, after implementing optimization for multiple simple property validations. new PropertyFromInfo { Destination = conceptInfo.Dependency_ChangesEntity, Source = activeSinceProperty }, historyActiveSinceProperty, new UniqueMultiplePropertiesInfo { DataStructure = conceptInfo.Dependency_ChangesEntity, PropertyNames = $"{currentProperty.Name} {historyActiveSinceProperty.Name}" } }); // InvalidData for history entity: it is not allowed to save with ActiveSince newer than current entity var denyFilterHistory = new QueryFilterExpressionInfo { Parameter = "Common.NewerThanCurrentEntry", Source = conceptInfo.Dependency_ChangesEntity, Expression = @"(items, parameter) => items.Where(item => item.ActiveSince > item.Entity.ActiveSince)" }; var invalidDataValidationHistory = new InvalidDataInfo { FilterType = "Common.NewerThanCurrentEntry", Source = conceptInfo.Dependency_ChangesEntity, ErrorMessage = "ActiveSince of history entry is not allowed to be newer than current entry." }; newConcepts.AddRange(new IConceptInfo[] { denyFilterHistory, invalidDataValidationHistory, new ParameterInfo { Module = new ModuleInfo { Name = "Common" }, Name = "NewerThanCurrentEntry" }, new InvalidDataMarkProperty2Info { InvalidData = invalidDataValidationHistory, MarkProperty = historyActiveSinceProperty } }); // Create ActiveUntil SqlQueryable: var activeUntilSqlQueryable = new SqlQueryableInfo { Module = conceptInfo.Entity.Module, Name = conceptInfo.Entity.Name + "_ChangesActiveUntil", SqlSource = ActiveUntilSqlSnippet(conceptInfo) }; newConcepts.AddRange(new IConceptInfo[] { activeUntilSqlQueryable, new DateTimePropertyInfo { DataStructure = activeUntilSqlQueryable, Name = "ActiveUntil" }, new SqlDependsOnDataStructureInfo { Dependent = activeUntilSqlQueryable, DependsOn = conceptInfo.Dependency_ChangesEntity }, new SqlDependsOnDataStructureInfo { Dependent = activeUntilSqlQueryable, DependsOn = conceptInfo.Entity }, new DataStructureExtendsInfo { Base = conceptInfo.Dependency_ChangesEntity, Extension = activeUntilSqlQueryable } }); // Configure History SqlQueryable: newConcepts.AddRange(new IConceptInfo[] { new SqlDependsOnDataStructureInfo { Dependent = historySqlQueryable, DependsOn = conceptInfo.Entity }, new SqlDependsOnDataStructureInfo { Dependent = historySqlQueryable, DependsOn = conceptInfo.Dependency_ChangesEntity }, new SqlDependsOnDataStructureInfo { Dependent = historySqlQueryable, DependsOn = activeUntilSqlQueryable }, new DateTimePropertyInfo { DataStructure = historySqlQueryable, Name = "ActiveUntil" }, new AllPropertiesFromInfo { Source = conceptInfo.Dependency_ChangesEntity, Destination = historySqlQueryable } }); // Configure AtTime SqlFunction: newConcepts.Add(new SqlDependsOnDataStructureInfo { Dependent = atTimeSqlFunction, DependsOn = historySqlQueryable }); return(newConcepts); }