Exemplo n.º 1
0
        public void CheckSemantics(IDslModel existingConcepts)
        {
            if (!(Subtype is IOrmDataStructure))
            {
                throw new DslSyntaxException(this, "Is (polymorphic) may only be used on a database-mapped data structure, such as Entity or SqlQueryable. "
                                             + this.Subtype.GetUserDescription() + " is not IOrmDataStructure.");
            }

            if (ImplementationName == null)
            {
                throw new DslSyntaxException(this, "ImplementationName must not be null. It is allowed to be an empty string.");
            }

            if (!string.IsNullOrEmpty(ImplementationName))
            {
                DslUtility.ValidateIdentifier(ImplementationName, this, "Invalid ImplementationName value.");
            }

            if (existingConcepts.FindByReference <PolymorphicMaterializedInfo>(pm => pm.Polymorphic, Supertype).Any())
            {
                // Verifying if the ChangesOnChangedItemsInfo can be created (see IsSubtypeOfMacro)
                var dependsOn = DslUtility.GetBaseChangesOnDependency(Subtype, existingConcepts);
                if (dependsOn.Count() == 0)
                {
                    throw new DslSyntaxException(this, Subtype.GetUserDescription() + " should be an *extension* of an entity. Otherwise it cannot be used in a materialized polymorphic entity because the system cannot detect when to update the persisted data.");
                }
            }
        }
Exemplo n.º 2
0
        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 PolymorphicSubtypeReferenceInfo
            {
                DataStructure = conceptInfo.Supertype,
                Referenced    = conceptInfo.Subtype,
                Name          = conceptInfo.GetSubtypeReferenceName()
            };

            newConcepts.Add(subtypeReference);
            newConcepts.Add(new PolymorphicPropertyInfo {
                Property = subtypeReference
            });                                                                           // Minor optimization to reduce the number of macro evaluations.

            // 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):

            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(" + GetComputeHashIdSelector(conceptInfo) + @").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(DslUtility.CopySqlDependencies(conceptInfo, implementationView, existingConcepts));

            return(newConcepts);
        }