/// <summary> /// Dispatches the call to the extensions. /// </summary> /// <param name="pi">The property info reflection object.</param> /// <param name="belongsToModel">The belongs to model.</param> /// <param name="model">The model.</param> public void ProcessBelongsTo(PropertyInfo pi, BelongsToModel belongsToModel, ActiveRecordModel model) { foreach(IModelBuilderExtension extension in extensions) { extension.ProcessBelongsTo(pi, belongsToModel, model); } }
/// <summary> /// Dispatches the call to the extensions. /// </summary> /// <param name="pi">The property info reflection object.</param> /// <param name="belongsToModel">The belongs to model.</param> /// <param name="model">The model.</param> public void ProcessBelongsTo(PropertyInfo pi, BelongsToModel belongsToModel, ActiveRecordModel model) { foreach (IModelBuilderExtension extension in extensions) { extension.ProcessBelongsTo(pi, belongsToModel, model); } }
public override void VisitBelongsTo(BelongsToModel model) { String cascade = TranslateCascadeEnum(model.BelongsToAtt.Cascade); String outerJoin = TranslateOuterJoin(model.BelongsToAtt.OuterJoin); AppendF("<many-to-one {0} {1} {2} {3} {4} {5} {6} {7} {8} {9}/>", MakeAtt("name", model.Property.Name), MakeAtt("access", model.BelongsToAtt.AccessString), MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)), MakeAtt("column", model.BelongsToAtt.Column), WriteIfFalse("insert", model.BelongsToAtt.Insert), WriteIfFalse("update", model.BelongsToAtt.Update), WriteIfTrue("not-null", model.BelongsToAtt.NotNull), WriteIfTrue("unique", model.BelongsToAtt.Unique), WriteIfNonNull("cascade", cascade), WriteIfNonNull("outer-join", outerJoin)); }
/// <summary> /// Visits the belongs to. /// </summary> /// <remarks> /// Infer column name and type /// Verify that the property is virtual if the class was marked lazy. /// </remarks> /// <param name="model">The model.</param> public override void VisitBelongsTo(BelongsToModel model) { if (currentModel.ActiveRecordAtt != null) { if (currentModel.ActiveRecordAtt.Lazy || (currentModel.ActiveRecordAtt.LazySpecified == false && ActiveRecordModel.isLazyByDefault)) { //Assuming that a property must have at least a single accessor MethodInfo accessor = model.Property.GetAccessors(true)[0]; if (!accessor.IsVirtual) { throw new ActiveRecordException( String.Format("Property {0} must be virtual because " + "class {1} support lazy loading [ActiveRecord(Lazy=true)]", model.Property.Name, model.Property.DeclaringType.Name)); } } } if (model.BelongsToAtt.Column == null && model.BelongsToAtt.CompositeKeyColumns == null) { model.BelongsToAtt.Column = model.Property.Name; } // Append column prefix if (model.BelongsToAtt.Column != null) { model.BelongsToAtt.Column = columnPrefix + model.BelongsToAtt.Column; } if (model.BelongsToAtt.Type == null) { model.BelongsToAtt.Type = model.Property.PropertyType; } JoinedTableModel joinedTable = ObtainJoinedTableIfPresent(model.Property, model.BelongsToAtt); if (joinedTable != null) { joinedTable.BelongsTo.Add(model); } }
public override void VisitBelongsTo(BelongsToModel model) { if (currentModel.ActiveRecordAtt.Lazy) { //Assuming that a property must have at least a single accessor MethodInfo accessor = model.Property.GetAccessors(true)[0]; if (!accessor.IsVirtual) { throw new ActiveRecordException( string.Format("Property {0} must be virtual because " + "class {1} support lazy loading [ActiveRecord(Lazy=true)]", model.Property.Name, model.Property.DeclaringType.Name)); } } if (model.BelongsToAtt.Column == null) { model.BelongsToAtt.Column = model.Property.Name; } if (model.BelongsToAtt.Type == null) { model.BelongsToAtt.Type = model.Property.PropertyType; } }
private void ProcessProperties(Type type, ActiveRecordModel model) { // Check persistent properties of the base class as well if (ShouldCheckBase(type)) { ProcessProperties(type.BaseType, model); } PropertyInfo[] props = type.GetProperties(DefaultBindingFlags); foreach(PropertyInfo prop in props) { bool isArProperty = false; AnyModel anyModel; HasManyToAnyModel hasManyToAnyModel; if (extension != null) { extension.ProcessProperty(prop, model); } object[] valAtts = prop.GetCustomAttributes(typeof(AbstractValidationAttribute), true); foreach(AbstractValidationAttribute valAtt in valAtts) { IValidator validator = valAtt.Build(); validator.Initialize(validatorRegistry, prop); model.Validators.Add(validator); } foreach(object attribute in prop.GetCustomAttributes(false)) { if (attribute is PrimaryKeyAttribute) { PrimaryKeyAttribute propAtt = attribute as PrimaryKeyAttribute; isArProperty = true; // Joined Subclasses must not have PrimaryKey if (type.IsDefined(typeof(JoinedBaseAttribute), true) && // JoinedBase in a superclass !type.IsDefined(typeof(JoinedBaseAttribute), false)) // but not here { throw new ActiveRecordException("You can't specify a PrimaryKeyAttribute in a joined subclass. " + "Check type " + model.Type.FullName); } if (prop.PropertyType.IsDefined(typeof(CompositeKeyAttribute), true)) { object[] att = prop.PropertyType.GetCustomAttributes(typeof(CompositeKeyAttribute), true); CompositeKeyAttribute cAtt = att[0] as CompositeKeyAttribute; model.CompositeKey = new CompositeKeyModel(prop, cAtt); } else { if (!propAtt.IsOverride && model.PrimaryKey != null) { throw new ActiveRecordException("You can't specify more than one PrimaryKeyAttribute in a " + "class. Check type " + model.Type.FullName); } model.PrimaryKey = new PrimaryKeyModel(prop, propAtt); } } else if (attribute is CompositeKeyAttribute) { CompositeKeyAttribute propAtt = attribute as CompositeKeyAttribute; isArProperty = true; model.CompositeKey = new CompositeKeyModel(prop, propAtt); } else if (attribute is AnyAttribute) { AnyAttribute anyAtt = attribute as AnyAttribute; isArProperty = true; anyModel = new AnyModel(prop, anyAtt); model.Anys.Add(anyModel); CollectMetaValues(anyModel.MetaValues, prop); } else if (attribute is PropertyAttribute) { PropertyAttribute propAtt = attribute as PropertyAttribute; isArProperty = true; // If this property overrides a base class property remove the old one if (propAtt.IsOverride) { for (int index = 0; index < model.Properties.Count; ++index) { PropertyModel oldModel = (PropertyModel)model.Properties[index]; if (oldModel.Property.Name == prop.Name) { model.Properties.RemoveAt(index); break; } } } PropertyModel propModel = new PropertyModel(prop, propAtt); model.Properties.Add(propModel); model.PropertyDictionary[prop.Name] = propModel; } else if (attribute is NestedAttribute) { NestedAttribute propAtt = attribute as NestedAttribute; isArProperty = true; ActiveRecordModel nestedModel = new ActiveRecordModel(prop.PropertyType); nestedModel.IsNestedType = true; Type nestedType = propAtt.MapType ?? prop.PropertyType; nestedModel.IsNestedCompositeType = model.IsNestedCompositeType; ProcessProperties(nestedType, nestedModel); ProcessFields(nestedType, nestedModel); NestedModel nested = new NestedModel(prop, propAtt, nestedModel); nestedModel.ParentNested = nested; model.Components.Add(nested); } else if (attribute is NestedParentReferenceAttribute) { NestedParentReferenceAttribute nestedParentAtt = attribute as NestedParentReferenceAttribute; isArProperty = true; model.ComponentParent.Add(new NestedParentReferenceModel(prop, nestedParentAtt)); } else if (attribute is JoinedKeyAttribute) { JoinedKeyAttribute propAtt = attribute as JoinedKeyAttribute; isArProperty = true; if (model.Key != null) { throw new ActiveRecordException("You can't specify more than one JoinedKeyAttribute. " + "Check type " + model.Type.FullName); } model.Key = new KeyModel(prop, propAtt); } else if (attribute is VersionAttribute) { VersionAttribute propAtt = attribute as VersionAttribute; isArProperty = true; if (model.Version != null) { throw new ActiveRecordException("You can't specify more than one VersionAttribute. " + "Check type " + model.Type.FullName); } model.Version = new VersionModel(prop, propAtt); } else if (attribute is TimestampAttribute) { TimestampAttribute propAtt = attribute as TimestampAttribute; isArProperty = true; if (model.Timestamp != null) { throw new ActiveRecordException("You can't specify more than one TimestampAttribute. " + "Check type " + model.Type.FullName); } model.Timestamp = new TimestampModel(prop, propAtt); } // Relations else if (attribute is OneToOneAttribute) { OneToOneAttribute propAtt = attribute as OneToOneAttribute; isArProperty = true; model.OneToOnes.Add(new OneToOneModel(prop, propAtt)); } else if (attribute is BelongsToAttribute) { BelongsToAttribute propAtt = attribute as BelongsToAttribute; isArProperty = true; BelongsToModel btModel = new BelongsToModel(prop, propAtt); model.BelongsTo.Add(btModel); model.BelongsToDictionary[prop.Name] = btModel; if (extension != null) { extension.ProcessBelongsTo(prop, btModel, model); } } // The ordering is important here, HasManyToAny must comes before HasMany! else if (attribute is HasManyToAnyAttribute) { HasManyToAnyAttribute propAtt = attribute as HasManyToAnyAttribute; isArProperty = true; hasManyToAnyModel = new HasManyToAnyModel(prop, propAtt); model.HasManyToAny.Add(hasManyToAnyModel); model.HasManyToAnyDictionary[prop.Name] = hasManyToAnyModel; CollectMetaValues(hasManyToAnyModel.MetaValues, prop); if (extension != null) { extension.ProcessHasManyToAny(prop, hasManyToAnyModel, model); } } else if (attribute is HasManyAttribute) { HasManyAttribute propAtt = attribute as HasManyAttribute; isArProperty = true; HasManyModel hasManyModel = new HasManyModel(prop, propAtt); if (propAtt.DependentObjects) { ActiveRecordModel dependentObjectModel = new ActiveRecordModel(propAtt.MapType); dependentObjectModel.IsNestedType = true; dependentObjectModel.IsNestedCompositeType = true; ProcessProperties(propAtt.MapType, dependentObjectModel); hasManyModel.DependentObjectModel = new DependentObjectModel(prop, propAtt, dependentObjectModel); } model.HasMany.Add(hasManyModel); model.HasManyDictionary[prop.Name] = hasManyModel; if (extension != null) { extension.ProcessHasMany(prop, hasManyModel, model); } } else if (attribute is HasAndBelongsToManyAttribute) { HasAndBelongsToManyAttribute propAtt = attribute as HasAndBelongsToManyAttribute; isArProperty = true; HasAndBelongsToManyModel habtManyModel = new HasAndBelongsToManyModel(prop, propAtt); model.HasAndBelongsToMany.Add(habtManyModel); model.HasAndBelongsToManyDictionary[prop.Name] = habtManyModel; if (extension != null) { extension.ProcessHasAndBelongsToMany(prop, habtManyModel, model); } } else if (attribute is Any.MetaValueAttribute) { if (prop.GetCustomAttributes(typeof(HasManyToAnyAttribute), false).Length == 0 && prop.GetCustomAttributes(typeof(AnyAttribute), false).Length == 0 ) throw new ActiveRecordException( "You can't specify an Any.MetaValue without specifying the Any or HasManyToAny attribute. " + "Check type " + prop.DeclaringType.FullName); } else if (attribute is CompositeUserTypeAttribute) { CompositeUserTypeAttribute propAtt = attribute as CompositeUserTypeAttribute; isArProperty = true; model.CompositeUserType.Add(new CompositeUserTypeModel(prop, propAtt)); } if (attribute is CollectionIDAttribute) { CollectionIDAttribute propAtt = attribute as CollectionIDAttribute; model.CollectionIDs.Add(new CollectionIDModel(prop, propAtt)); } if (attribute is HiloAttribute) { HiloAttribute propAtt = attribute as HiloAttribute; model.Hilos.Add(new HiloModel(prop, propAtt)); } } if (!isArProperty) { model.NotMappedProperties.Add(prop); } } }
/// <summary> /// Visits the belongs to. /// </summary> /// <param name="model">The model.</param> public override void VisitBelongsTo(BelongsToModel model) { if (!AppliesToCurrentTable(model.BelongsToAtt)) { return; } String cascade = TranslateCascadeEnum(model.BelongsToAtt.Cascade); String fetch = TranslateFetch(model.BelongsToAtt.Fetch); String notFoundMode = TranslateNotFoundBehaviourEnum(model.BelongsToAtt.NotFoundBehaviour); if (model.BelongsToAtt.Column == null) { AppendF("<many-to-one{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}>", MakeAtt("name", model.Property.Name), MakeAtt("access", model.BelongsToAtt.AccessString), MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)), WriteIfTrue("not-null", model.BelongsToAtt.NotNull), WriteIfTrue("unique", model.BelongsToAtt.Unique), WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey), WriteIfNonNull("cascade", cascade), WriteIfNonNull("fetch", fetch), WriteIfFalse("update", model.BelongsToAtt.Update), WriteIfFalse("insert", model.BelongsToAtt.Insert), WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef), WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey), WriteIfNonNull("not-found", notFoundMode)); Ident(); WriteCompositeColumns(model.BelongsToAtt.CompositeKeyColumns); Dedent(); Append("</many-to-one>"); } else { AppendF("<many-to-one{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13} />", MakeAtt("name", model.Property.Name), MakeAtt("access", model.BelongsToAtt.AccessString), MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)), MakeAtt("column", model.BelongsToAtt.Column), WriteIfFalse("insert", model.BelongsToAtt.Insert), WriteIfFalse("update", model.BelongsToAtt.Update), WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef), WriteIfTrue("not-null", model.BelongsToAtt.NotNull), WriteIfTrue("unique", model.BelongsToAtt.Unique), WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey), WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey), WriteIfNonNull("cascade", cascade), WriteIfNonNull("fetch", fetch), WriteIfNonNull("not-found", notFoundMode)); } }
private void ProcessProperties(Type type, ActiveRecordModel model) { // Check persistent properties of the base class as well if (ShouldCheckBase(type)) { ProcessProperties(type.BaseType, model); } PropertyInfo[] props = type.GetProperties(DefaultBindingFlags); foreach (PropertyInfo prop in props) { bool isArProperty = false; AnyModel anyModel; HasManyToAnyModel hasManyToAnyModel; if (extension != null) { extension.ProcessProperty(prop, model); } object[] valAtts = prop.GetCustomAttributes(typeof(AbstractValidationAttribute), true); foreach (AbstractValidationAttribute valAtt in valAtts) { IValidator validator = valAtt.Build(); validator.Initialize(validatorRegistry, prop); model.Validators.Add(validator); } foreach (object attribute in prop.GetCustomAttributes(false)) { if (attribute is PrimaryKeyAttribute) { PrimaryKeyAttribute propAtt = attribute as PrimaryKeyAttribute; isArProperty = true; // Joined Subclasses must not have PrimaryKey if (HasJoinedBase(type)) { throw new ActiveRecordException("You can't specify a PrimaryKeyAttribute in a joined subclass. " + "Check type " + model.Type.FullName); } if (prop.PropertyType.IsDefined(typeof(CompositeKeyAttribute), true)) { object[] att = prop.PropertyType.GetCustomAttributes(typeof(CompositeKeyAttribute), true); CompositeKeyAttribute cAtt = att[0] as CompositeKeyAttribute; model.CompositeKey = new CompositeKeyModel(prop, cAtt); } else { if (!propAtt.IsOverride && model.PrimaryKey != null) { throw new ActiveRecordException("You can't specify more than one PrimaryKeyAttribute in a " + "class. Check type " + model.Type.FullName); } model.PrimaryKey = new PrimaryKeyModel(prop, propAtt); } } else if (attribute is CompositeKeyAttribute) { CompositeKeyAttribute propAtt = attribute as CompositeKeyAttribute; isArProperty = true; model.CompositeKey = new CompositeKeyModel(prop, propAtt); } else if (attribute is AnyAttribute) { AnyAttribute anyAtt = attribute as AnyAttribute; isArProperty = true; anyModel = new AnyModel(prop, anyAtt); model.Anys.Add(anyModel); CollectMetaValues(anyModel.MetaValues, prop); } else if (attribute is PropertyAttribute) { PropertyAttribute propAtt = attribute as PropertyAttribute; isArProperty = true; // If this property overrides a base class property remove the old one if (propAtt.IsOverride) { for (int index = 0; index < model.Properties.Count; ++index) { PropertyModel oldModel = (PropertyModel)model.Properties[index]; if (oldModel.Property.Name == prop.Name) { model.Properties.RemoveAt(index); break; } } } PropertyModel propModel = new PropertyModel(prop, propAtt); model.Properties.Add(propModel); model.PropertyDictionary[prop.Name] = propModel; } else if (attribute is NestedAttribute) { NestedAttribute propAtt = attribute as NestedAttribute; isArProperty = true; ActiveRecordModel nestedModel = new ActiveRecordModel(prop.PropertyType); nestedModel.IsNestedType = true; Type nestedType = propAtt.MapType ?? prop.PropertyType; nestedModel.IsNestedCompositeType = model.IsNestedCompositeType; ProcessProperties(nestedType, nestedModel); ProcessFields(nestedType, nestedModel); NestedModel nested = new NestedModel(prop, propAtt, nestedModel); nestedModel.ParentNested = nested; model.Components.Add(nested); } else if (attribute is NestedParentReferenceAttribute) { NestedParentReferenceAttribute nestedParentAtt = attribute as NestedParentReferenceAttribute; isArProperty = true; model.ComponentParent.Add(new NestedParentReferenceModel(prop, nestedParentAtt)); } else if (attribute is JoinedKeyAttribute) { JoinedKeyAttribute propAtt = attribute as JoinedKeyAttribute; isArProperty = true; if (model.Key != null) { throw new ActiveRecordException("You can't specify more than one JoinedKeyAttribute. " + "Check type " + model.Type.FullName); } model.Key = new KeyModel(prop, propAtt); } else if (attribute is VersionAttribute) { VersionAttribute propAtt = attribute as VersionAttribute; isArProperty = true; if (model.Version != null) { throw new ActiveRecordException("You can't specify more than one VersionAttribute. " + "Check type " + model.Type.FullName); } model.Version = new VersionModel(prop, propAtt); } else if (attribute is TimestampAttribute) { TimestampAttribute propAtt = attribute as TimestampAttribute; isArProperty = true; if (model.Timestamp != null) { throw new ActiveRecordException("You can't specify more than one TimestampAttribute. " + "Check type " + model.Type.FullName); } model.Timestamp = new TimestampModel(prop, propAtt); } // Relations else if (attribute is OneToOneAttribute) { OneToOneAttribute propAtt = attribute as OneToOneAttribute; isArProperty = true; model.OneToOnes.Add(new OneToOneModel(prop, propAtt)); } else if (attribute is BelongsToAttribute) { BelongsToAttribute propAtt = attribute as BelongsToAttribute; isArProperty = true; BelongsToModel btModel = new BelongsToModel(prop, propAtt); model.BelongsTo.Add(btModel); model.BelongsToDictionary[prop.Name] = btModel; if (extension != null) { extension.ProcessBelongsTo(prop, btModel, model); } } // The ordering is important here, HasManyToAny must comes before HasMany! else if (attribute is HasManyToAnyAttribute) { HasManyToAnyAttribute propAtt = attribute as HasManyToAnyAttribute; isArProperty = true; hasManyToAnyModel = new HasManyToAnyModel(prop, propAtt); model.HasManyToAny.Add(hasManyToAnyModel); model.HasManyToAnyDictionary[prop.Name] = hasManyToAnyModel; CollectMetaValues(hasManyToAnyModel.MetaValues, prop); if (extension != null) { extension.ProcessHasManyToAny(prop, hasManyToAnyModel, model); } } else if (attribute is HasManyAttribute) { HasManyAttribute propAtt = attribute as HasManyAttribute; isArProperty = true; HasManyModel hasManyModel = new HasManyModel(prop, propAtt, model); if (propAtt.DependentObjects) { ActiveRecordModel dependentObjectModel = new ActiveRecordModel(propAtt.MapType); dependentObjectModel.IsNestedType = true; dependentObjectModel.IsNestedCompositeType = true; ProcessProperties(propAtt.MapType, dependentObjectModel); hasManyModel.DependentObjectModel = new DependentObjectModel(prop, propAtt, dependentObjectModel); } model.HasMany.Add(hasManyModel); model.HasManyDictionary[prop.Name] = hasManyModel; if (extension != null) { extension.ProcessHasMany(prop, hasManyModel, model); } } else if (attribute is HasAndBelongsToManyAttribute) { HasAndBelongsToManyAttribute propAtt = attribute as HasAndBelongsToManyAttribute; isArProperty = true; HasAndBelongsToManyModel habtManyModel = new HasAndBelongsToManyModel(prop, propAtt); model.HasAndBelongsToMany.Add(habtManyModel); model.HasAndBelongsToManyDictionary[prop.Name] = habtManyModel; if (extension != null) { extension.ProcessHasAndBelongsToMany(prop, habtManyModel, model); } } else if (attribute is Any.MetaValueAttribute) { if (prop.GetCustomAttributes(typeof(HasManyToAnyAttribute), false).Length == 0 && prop.GetCustomAttributes(typeof(AnyAttribute), false).Length == 0 ) { throw new ActiveRecordException( "You can't specify an Any.MetaValue without specifying the Any or HasManyToAny attribute. " + "Check type " + prop.DeclaringType.FullName); } } else if (attribute is CompositeUserTypeAttribute) { CompositeUserTypeAttribute propAtt = attribute as CompositeUserTypeAttribute; isArProperty = true; model.CompositeUserType.Add(new CompositeUserTypeModel(prop, prop.PropertyType, propAtt)); } if (attribute is CollectionIDAttribute) { CollectionIDAttribute propAtt = attribute as CollectionIDAttribute; model.CollectionIDs.Add(new CollectionIDModel(prop, propAtt)); } if (attribute is HiloAttribute) { HiloAttribute propAtt = attribute as HiloAttribute; model.Hilos.Add(new HiloModel(prop, propAtt)); } } if (!isArProperty) { model.NotMappedProperties.Add(prop); } } }
public virtual void VisitBelongsTo(BelongsToModel model) { }
/// <summary> /// Visits the belongs to. /// </summary> /// <param name="model">The model.</param> public virtual void VisitBelongsTo(BelongsToModel model) { }
public String CreateControl(ActiveRecordModel model, String prefix, BelongsToModel belongsToModel, object instance) { stringBuilder.Length = 0; PropertyInfo prop = belongsToModel.Property; prefix += "." + prop.Name; ActiveRecordModel otherModel = ActiveRecordModel.GetModel(belongsToModel.BelongsToAtt.Type); PrimaryKeyModel keyModel = ObtainPKProperty(otherModel); if (otherModel == null || keyModel == null) { return "Model not found or PK not found"; } object[] items = CommonOperationUtils.FindAll(otherModel.Type); String propName = CreatePropName(model, prefix, keyModel.Property.Name); stringBuilder.Append(LabelFor(propName, TextHelper.PascalCaseToWord(prop.Name) + ": ")); IDictionary attrs = new HybridDictionary(true); attrs["value"] = keyModel.Property.Name; if (!belongsToModel.BelongsToAtt.NotNull) { attrs.Add("firstOption", "Empty"); attrs.Add("firstOptionValue", ""); } stringBuilder.Append(Select(propName, items, attrs)); return stringBuilder.ToString(); }
public bool CanHandle(BelongsToModel model) { return CheckModelAndKeyAreAccessible(model.BelongsToAtt.Type); }
/// <summary> /// Visits the belongs to. /// </summary> /// <param name="model">The model.</param> public override void VisitBelongsTo(BelongsToModel model) { if (!AppliesToCurrentTable(model.BelongsToAtt)) { return; } String cascade = TranslateCascadeEnum(model.BelongsToAtt.Cascade); String fetch = TranslateFetch(model.BelongsToAtt.Fetch); String notFoundMode = TranslateNotFoundBehaviourEnum(model.BelongsToAtt.NotFoundBehaviour); String lazy = TranslateLazy(model.BelongsToAtt.Lazy); if (model.BelongsToAtt.Column == null) { AppendStartTag("many-to-one", MakeAtt("name", model.Property.Name), MakeAtt("access", model.BelongsToAtt.AccessString), MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)), WriteIfTrue("not-null", model.BelongsToAtt.NotNull), WriteIfTrue("unique", model.BelongsToAtt.Unique), WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey), WriteIfNonNull("index", model.BelongsToAtt.Index), WriteIfNonNull("cascade", cascade), WriteIfNonNull("fetch", fetch), WriteIfNonNull("lazy", lazy), WriteIfFalse("update", model.BelongsToAtt.Update), WriteIfFalse("insert", model.BelongsToAtt.Insert), WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef), WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey), WriteIfFalse("optimistic-lock", model.BelongsToAtt.OptimisticLock), WriteIfNonNull("not-found", notFoundMode)); Ident(); WriteCompositeColumns(model.BelongsToAtt.CompositeKeyColumns); Dedent(); Append("</many-to-one>"); } else { AppendFullTag("many-to-one", MakeAtt("name", model.Property.Name), MakeAtt("access", model.BelongsToAtt.AccessString), MakeAtt("class", MakeTypeName(model.BelongsToAtt.Type)), MakeAtt("column", model.BelongsToAtt.Column), WriteIfFalse("insert", model.BelongsToAtt.Insert), WriteIfFalse("update", model.BelongsToAtt.Update), WriteIfNonNull("property-ref", model.BelongsToAtt.PropertyRef), WriteIfTrue("not-null", model.BelongsToAtt.NotNull), WriteIfTrue("unique", model.BelongsToAtt.Unique), WriteIfNonNull("unique-key", model.BelongsToAtt.UniqueKey), WriteIfNonNull("foreign-key", model.BelongsToAtt.ForeignKey), WriteIfNonNull("index", model.BelongsToAtt.Index), WriteIfNonNull("cascade", cascade), WriteIfNonNull("fetch", fetch), WriteIfNonNull("lazy", lazy), WriteIfFalse("optimistic-lock", model.BelongsToAtt.OptimisticLock), WriteIfNonNull("not-found", notFoundMode)); } }
public override void VisitHasMany(HasManyModel model) { model.HasManyAtt.RelationType = GuessRelation(model.Property, model.HasManyAtt.RelationType); if (model.HasManyAtt.RelationType == RelationType.IdBag) { throw new ActiveRecordException(String.Format( "You can't use idbags in a many to one association (HasMany) {0}.{1} ", model.Property.DeclaringType.Name, model.Property.Name)); } if (model.HasManyAtt.RelationType == RelationType.Map && model.HasManyAtt.Index == null) { throw new ActiveRecordException(String.Format( "A HasMany with type Map requires that you specify an 'Index', use the Index property {0}.{1} ", model.Property.DeclaringType.Name, model.Property.Name)); } // Infer table and column based on possible belongs to // on the target class String table = model.HasManyAtt.Table; String keyColumn = model.HasManyAtt.ColumnKey; ActiveRecordModel target = arCollection[model.HasManyAtt.MapType]; if ((table == null || keyColumn == null) && target == null) { throw new ActiveRecordException(String.Format( "ActiveRecord tried to infer details about the relation {0}.{1} but " + "it could not find information about the specified target type {2}", model.Property.DeclaringType.Name, model.Property.Name, model.HasManyAtt.MapType)); } BelongsToModel targetBtModel = null; if (target != null) { foreach (BelongsToModel btModel in target.BelongsTo) { if (btModel.BelongsToAtt.Type == model.Property.DeclaringType || btModel.Property.PropertyType == model.Property.DeclaringType) { targetBtModel = btModel; break; } } } if ((table == null || keyColumn == null) && targetBtModel == null) { throw new ActiveRecordException(String.Format( "ActiveRecord tried to infer details about the relation {0}.{1} but " + "it could not find a 'BelongsTo' mapped property in the target type {2}", model.Property.DeclaringType.Name, model.Property.Name, model.HasManyAtt.MapType)); } if (target != null) { VisitModel(target); } if (table == null) { table = target.ActiveRecordAtt.Table; } if (keyColumn == null) { keyColumn = targetBtModel.BelongsToAtt.Column; } model.HasManyAtt.Table = table; model.HasManyAtt.ColumnKey = keyColumn; }
/// <summary> /// Visits the has many. /// </summary> /// <remarks> /// Guess the type of the relation, if not specified explicitly /// Verify that the assoication is valid on [HasMany] /// Validate that required information is specified /// Infer the other side of the assoication and grab require data from it /// </remarks> /// <param name="model">The model.</param> public override void VisitHasMany(HasManyModel model) { if (model.HasManyAtt.MapType == null) { model.HasManyAtt.MapType = GuessType(null, model.Property.PropertyType); } model.HasManyAtt.RelationType = GuessRelation(model.Property, model.HasManyAtt.RelationType); // Guess the details about a map relation if needed if (model.HasManyAtt.RelationType == RelationType.Map) { if (string.IsNullOrEmpty(model.HasManyAtt.Table)) { model.HasManyAtt.Table = string.Format("{0}_{1}", model.Property.ReflectedType.Name, model.Property.Name); } if (model.HasManyAtt.IndexType == null) { model.HasManyAtt.IndexType = GetIndexTypeFromDictionary(model.Property.PropertyType).Name; } if (model.HasManyAtt.MapType == null) { model.HasManyAtt.MapType = GetMapTypeFromDictionary(model.Property.PropertyType); } } if (model.HasManyAtt.RelationType == RelationType.IdBag) { throw new ActiveRecordException(String.Format( "You can't use idbags in a many to one association (HasMany) {0}.{1} ", model.Property.DeclaringType.Name, model.Property.Name)); } if (model.HasManyAtt.RelationType == RelationType.Map && model.HasManyAtt.Index == null) { throw new ActiveRecordException(String.Format( "A HasMany with type Map requires that you specify an 'Index', use the Index property {0}.{1} ", model.Property.DeclaringType.Name, model.Property.Name)); } if (model.HasManyAtt.RelationType == RelationType.List && model.HasManyAtt.Index == null) { throw new ActiveRecordException(String.Format( "A HasMany with type List requires that you specify an 'Index', use the Index property {0}.{1} ", model.Property.DeclaringType.Name, model.Property.Name)); } // try to guess an <element> mapping if none of the mapping properties was set if (model.HasManyAtt.MapType.IsValueType && string.IsNullOrEmpty(model.HasManyAtt.Element) && model.HasManyAtt.ElementType == null && string.IsNullOrEmpty(model.HasManyAtt.ColumnKey)) { GuessElementMappingBasedOnEnum(model); } // Infer table and column based on possible belongs to // on the target class String table = model.HasManyAtt.Table; String keyColumn = model.HasManyAtt.ColumnKey; String[] compositeKeyColumnKeys = model.HasManyAtt.CompositeKeyColumnKeys; Type type = model.HasManyAtt.MapType; ActiveRecordModel target = arCollection[type]; if ((table == null || (keyColumn == null && compositeKeyColumnKeys == null)) && target == null) { throw new ActiveRecordException(String.Format( "ActiveRecord tried to infer details about the relation {0}.{1} but " + "it could not find information about the specified target type {2}. If you have mapped a Collection or Dictionary of value types, please make sure you have specified the Table property.", model.Property.DeclaringType.Name, model.Property.Name, type)); } BelongsToModel targetBtModel = null; ActiveRecordModel tmpModel = target; while (tmpModel != null && targetBtModel == null) { foreach (BelongsToModel btModel in tmpModel.BelongsTo) { if (btModel.BelongsToAtt.Type != model.Property.DeclaringType && btModel.BelongsToAtt.Type != model.ContainingTypeModel.Type && btModel.Property.PropertyType != model.Property.DeclaringType && btModel.Property.PropertyType != model.ContainingTypeModel.Type) { continue; } targetBtModel = btModel; break; } tmpModel = tmpModel.Parent; } if ((table == null || (keyColumn == null && compositeKeyColumnKeys == null)) && targetBtModel == null) { throw new ActiveRecordException(String.Format( "ActiveRecord tried to infer details about the relation {0}.{1} but " + "it could not find a 'BelongsTo' mapped property in the target type {2}", model.Property.DeclaringType.Name, model.Property.Name, type)); } if (target != null) { VisitModel(target); } else if (model.HasManyAtt.DependentObjects) { VisitDependentObject(model.DependentObjectModel); } if (table == null) { table = target.ActiveRecordAtt.Table; } if (targetBtModel != null) { if (keyColumn == null && targetBtModel.BelongsToAtt.CompositeKeyColumns == null) { keyColumn = targetBtModel.BelongsToAtt.Column; } else { compositeKeyColumnKeys = targetBtModel.BelongsToAtt.CompositeKeyColumns; } } model.HasManyAtt.Table = table; if (keyColumn != null) { model.HasManyAtt.ColumnKey = keyColumn; } else { model.HasManyAtt.CompositeKeyColumnKeys = compositeKeyColumnKeys; } }