private void PopulateClass(ModelClass cls, IDbConnection connection, IDbHelper helper) { if (cls != null && connection != null) { // Relations to this class (this class has the primary key) List <Relation> relationsTo = helper.GetPKRelations(cls); // If the other side of the relation (FK part) is not in our model, we won't // need the relation at all _manager.FilterPKRelations(relationsTo); // Relations from this class (this class has the foreign key) List <Relation> relationsFrom = helper.GetFKRelations(cls); // If the other side of the relation (PK part) is not in our model, we won't // need the relation at all _manager.FilterFKRelations(relationsFrom); // Properties List <Column> columns = helper.GetProperties(cls); if (columns != null && columns.Count > 0) { List <Column> secondPass = new List <Column>(); foreach (Column column in columns) { // We'll handle primary and foreigns later. First, we'll create ordinary properties. if (column.Primary || (column.ForeignConstraints.Count > 0 && (Relation.GetCountOfMatchingRelations(relationsTo, column.ForeignConstraints) > 0 || Relation.GetCountOfMatchingRelations(relationsFrom, column.ForeignConstraints) > 0) ) ) { secondPass.Add(column); } else { _manager.NewProperty(cls, column).ColumnType = helper.GetNHibernateType(column.DataType); } } // Keys List <Column> primaryKeys = null; if (secondPass.Count > 0) { primaryKeys = Column.FindPrimaryKeys(secondPass); if (primaryKeys != null && primaryKeys.Count > 0) { // Create primary and composite keys if (primaryKeys.Count == 1) { ModelProperty keyProperty = _manager.NewPrimaryKey(cls, primaryKeys[0]); keyProperty.ColumnType = helper.GetNHibernateType(primaryKeys[0].DataType); SetGenerator(keyProperty); } else { string keyClassName = cls.Name + Common.CompositeClassNameSuffix; foreach (Column key in primaryKeys) { ModelProperty keyProperty = _manager.NewCompositeKey(cls, key, keyClassName); keyProperty.ColumnType = helper.GetNHibernateType(key.DataType); SetGenerator(keyProperty); } } } } if (relationsTo != null && relationsTo.Count > 0) { foreach (Relation relation in relationsTo) { relation.PrimaryModelClass = cls; } } _relations.AddRange(relationsTo); if (relationsFrom != null && relationsFrom.Count > 0) { foreach (Relation relation in relationsFrom) { relation.ForeignModelClass = cls; } _relations.AddRange(relationsFrom); // To define many to many and one to one, we need to know the pattern of foreign keys. if (primaryKeys != null && primaryKeys.Count > 0) { foreach (Column key in primaryKeys) { Relation relation = Relation.GetForeginColumn(relationsFrom, key); if (relation != null) { relation.IsForeignColumnPrimary = true; } } } } } } }
/// <summary> /// OnDragDrop is used to create classes corresponding to the selection dragged /// from the Server Explorer /// </summary> private void OnDragDrop(object sender, DragEventArgs e) { // Check if the data present is in the DSRef format if (e.Data.GetDataPresent(DSRefNavigator.DataSourceReferenceFormat)) { try { // Create a navigator for the DSRef Consumer (and dispose it when finished) using (DSRefNavigator navigator = new DSRefNavigator(e.Data.GetData( DSRefNavigator.DataSourceReferenceFormat) as Stream)) { _output = new OutputWindowHelper(DTEHelper.GetDTE(this.Store)); // Get connection info of the connection of selected tables string providerType = null; IDbConnection connection = ServerExplorerHelper.GetConnection(navigator, out providerType); IDbHelper helper; switch (providerType) { case "System.Data.SqlClient.SqlConnection": helper = new SqlHelper(connection); break; case "System.Data.OracleClient.OracleConnection": case "Oracle.DataAccess.Client.OracleConnection": Log("Selecting Oracle Helper for provider " + providerType); helper = new OracleHelper(connection); break; case "MySql.Data.MySqlClient.MySqlConnection": helper = new MySqlHelper(connection); break; default: // TODO: Support other databases with native providers. Log( string.Format( @"Failed: ActiveWriter does not support model generation through {0}. Supported providers: System.Data.SqlClient.SqlConnection, System.Data.OracleClient.OracleConnection, Oracle.DataAccess.Client.OracleConnection, MySql.Data.MySqlClient.MySqlConnection. You can help us improve this functionality, though. See http://www.castleproject.org/others/contrib/index.html to access ActiveWriter source code under the contrib repository, and check Dsl\ServerExplorerSupport\IDbHelper.cs for the start.", providerType)); return; } // Get the root element where we'll add the classes Model model = Helper.GetModel(this.Store); if (model == null) { Log("Failed: Cannot get the model for the store."); return; } _manager = new DiagramManager(this.Store, model); _manager.OutputWindow = _output; // Create a transaction to add the clases. using (Transaction txAdd = model.Store.TransactionManager.BeginTransaction("Add classes")) { List <DSRefNode> tableList = new List <DSRefNode>(); // Get the tables from the Server Explorer selection // We'll iterate this list twice to use nodes' list to // determine if we have to generate relations for each // table or not. foreach (DSRefNode node in navigator.ChildTableNodes) { tableList.Add(node); } _manager.Tables = tableList; _relations = new List <Relation>(); foreach (DSRefNode node in tableList) { // Create the table and add it to the model ModelClass cls = _manager.NewClass(node.Owner, node.Name); PopulateClass(cls, connection, helper); _manager.AssignModel(cls); } // Create relations if (_relations != null && _relations.Count > 0) { HandleRelations(); } // Commit the transaction and add tables to the model txAdd.Commit(); } // TODO: Auto layout doesn't work well. Will check with future versions of DSL tools. // this.AutoLayoutShapeElements(this.NestedChildShapes); } } catch (Exception ex) { Debug.WriteLine(ex.Message); } finally { _manager = null; _relations = null; _output = null; } } }
private static void ReadOneToOneRelationInstance(DslModeling::SerializationContext serializationContext, ModelClass element, global::System.Xml.XmlReader reader) { if (DslModeling::DomainRoleInfo.GetElementLinks<OneToOneRelation> (element, OneToOneRelation.SourceDomainRoleId).Count > 0) { // Only allow one instance, which already exists, so skip everything DslModeling::SerializationUtilities.Skip(reader); // Moniker contains no child XML elements, so just skip. return; } while (!serializationContext.Result.Failed && !reader.EOF && reader.NodeType == global::System.Xml.XmlNodeType.Element) { DslModeling::DomainClassXmlSerializer newOneToOneRelationSerializer = serializationContext.Directory.GetSerializer(OneToOneRelation.DomainClassId); global::System.Diagnostics.Debug.Assert(newOneToOneRelationSerializer != null, "Cannot find serializer for OneToOneRelation!"); OneToOneRelation newOneToOneRelation = newOneToOneRelationSerializer.TryCreateInstance (serializationContext, reader, element.Partition) as OneToOneRelation; if (newOneToOneRelation != null) { DslModeling::DomainRoleInfo.SetRolePlayer (newOneToOneRelation, OneToOneRelation.SourceDomainRoleId, element); DslModeling::DomainClassXmlSerializer targetSerializer = serializationContext.Directory.GetSerializer (newOneToOneRelation.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert (targetSerializer != null, "Cannot find serializer for " + newOneToOneRelation.GetDomainClass().Name + "!"); targetSerializer.Read(serializationContext, newOneToOneRelation, reader); break; // Only allow one instance. } else { // Maybe the relationship is serialized in short-form by mistake. DslModeling::DomainClassXmlSerializer newModelClassMonikerOfOneToOneRelationSerializer = serializationContext.Directory.GetSerializer(ModelClass.DomainClassId); global::System.Diagnostics.Debug.Assert(newModelClassMonikerOfOneToOneRelationSerializer != null, "Cannot find serializer for ModelClass!"); DslModeling::Moniker newModelClassMonikerOfOneToOneRelation = newModelClassMonikerOfOneToOneRelationSerializer.TryCreateMonikerInstance(serializationContext, reader, element, OneToOneRelation.DomainClassId, element.Partition); if (newModelClassMonikerOfOneToOneRelation != null) { ActiveWriterSerializationBehaviorSerializationMessages.ExpectingFullFormRelationship(serializationContext, reader, typeof(OneToOneRelation)); new OneToOneRelation(element.Partition, new DslModeling::RoleAssignment(OneToOneRelation.SourceDomainRoleId, element), new DslModeling::RoleAssignment(OneToOneRelation.TargetDomainRoleId, newModelClassMonikerOfOneToOneRelation)); DslModeling::SerializationUtilities.Skip(reader); // Moniker contains no child XML elements, so just skip. break; // Only allow one instance. } else { // Unknown element, skip. DslModeling::SerializationUtilities.Skip(reader); } } } }
private static void WriteChildElements(DslModeling::SerializationContext serializationContext, ModelClass element, global::System.Xml.XmlWriter writer) { // ManyToOneRelation global::System.Collections.ObjectModel.ReadOnlyCollection<ManyToOneRelation> allManyToOneRelationInstances = ManyToOneRelation.GetLinksToTargets(element); if (!serializationContext.Result.Failed && allManyToOneRelationInstances.Count > 0) { writer.WriteStartElement("targets"); foreach (ManyToOneRelation eachManyToOneRelationInstance in allManyToOneRelationInstances) { if (serializationContext.Result.Failed) break; DslModeling::DomainClassXmlSerializer relSerializer = serializationContext.Directory.GetSerializer(eachManyToOneRelationInstance.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert(relSerializer != null, "Cannot find serializer for " + eachManyToOneRelationInstance.GetDomainClass().Name + "!"); relSerializer.Write(serializationContext, eachManyToOneRelationInstance, writer); } writer.WriteEndElement(); } // ClassHasProperty global::System.Collections.ObjectModel.ReadOnlyCollection<ClassHasProperty> allClassHasPropertyInstances = ClassHasProperty.GetLinksToProperties(element); if (!serializationContext.Result.Failed && allClassHasPropertyInstances.Count > 0) { writer.WriteStartElement("properties"); global::System.Type typeofClassHasProperty = typeof(ClassHasProperty); foreach (ClassHasProperty eachClassHasPropertyInstance in allClassHasPropertyInstances) { if (serializationContext.Result.Failed) break; if (eachClassHasPropertyInstance.GetType() != typeofClassHasProperty) { // Derived relationships will be serialized in full-form. DslModeling::DomainClassXmlSerializer derivedRelSerializer = serializationContext.Directory.GetSerializer(eachClassHasPropertyInstance.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert(derivedRelSerializer != null, "Cannot find serializer for " + eachClassHasPropertyInstance.GetDomainClass().Name + "!"); derivedRelSerializer.Write(serializationContext, eachClassHasPropertyInstance, writer); } else { // No need to serialize the relationship itself, just serialize the role-player directly. DslModeling::ModelElement targetElement = eachClassHasPropertyInstance.Property; DslModeling::DomainClassXmlSerializer targetSerializer = serializationContext.Directory.GetSerializer(targetElement.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert(targetSerializer != null, "Cannot find serializer for " + targetElement.GetDomainClass().Name + "!"); targetSerializer.Write(serializationContext, targetElement, writer); } } writer.WriteEndElement(); } // ManyToManyRelation global::System.Collections.ObjectModel.ReadOnlyCollection<ManyToManyRelation> allManyToManyRelationInstances = ManyToManyRelation.GetLinksToManyToManyTargets(element); if (!serializationContext.Result.Failed && allManyToManyRelationInstances.Count > 0) { writer.WriteStartElement("manyToManyTargets"); foreach (ManyToManyRelation eachManyToManyRelationInstance in allManyToManyRelationInstances) { if (serializationContext.Result.Failed) break; DslModeling::DomainClassXmlSerializer relSerializer = serializationContext.Directory.GetSerializer(eachManyToManyRelationInstance.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert(relSerializer != null, "Cannot find serializer for " + eachManyToManyRelationInstance.GetDomainClass().Name + "!"); relSerializer.Write(serializationContext, eachManyToManyRelationInstance, writer); } writer.WriteEndElement(); } // OneToOneRelation OneToOneRelation theOneToOneRelationInstance = OneToOneRelation.GetLinkToOneToOneTarget(element); if (!serializationContext.Result.Failed && theOneToOneRelationInstance != null) { writer.WriteStartElement("oneToOneTarget"); DslModeling::DomainClassXmlSerializer relSerializer = serializationContext.Directory.GetSerializer(theOneToOneRelationInstance.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert(relSerializer != null, "Cannot find serializer for " + theOneToOneRelationInstance.GetDomainClass().Name + "!"); relSerializer.Write(serializationContext, theOneToOneRelationInstance, writer); writer.WriteEndElement(); } }
private static void ReadManyToManyRelationInstances(DslModeling::SerializationContext serializationContext, ModelClass element, global::System.Xml.XmlReader reader) { while (!serializationContext.Result.Failed && !reader.EOF && reader.NodeType == global::System.Xml.XmlNodeType.Element) { DslModeling::DomainClassXmlSerializer newManyToManyRelationSerializer = serializationContext.Directory.GetSerializer(ManyToManyRelation.DomainClassId); global::System.Diagnostics.Debug.Assert(newManyToManyRelationSerializer != null, "Cannot find serializer for ManyToManyRelation!"); ManyToManyRelation newManyToManyRelation = newManyToManyRelationSerializer.TryCreateInstance (serializationContext, reader, element.Partition) as ManyToManyRelation; if (newManyToManyRelation != null) { DslModeling::DomainRoleInfo.SetRolePlayer (newManyToManyRelation, ManyToManyRelation.SourceDomainRoleId, element); DslModeling::DomainClassXmlSerializer targetSerializer = serializationContext.Directory.GetSerializer (newManyToManyRelation.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert (targetSerializer != null, "Cannot find serializer for " + newManyToManyRelation.GetDomainClass().Name + "!"); targetSerializer.Read(serializationContext, newManyToManyRelation, reader); } else { // Maybe the relationship is serialized in short-form by mistake. DslModeling::DomainClassXmlSerializer newModelClassMonikerOfManyToManyRelationSerializer = serializationContext.Directory.GetSerializer(ModelClass.DomainClassId); global::System.Diagnostics.Debug.Assert(newModelClassMonikerOfManyToManyRelationSerializer != null, "Cannot find serializer for ModelClass!"); DslModeling::Moniker newModelClassMonikerOfManyToManyRelation = newModelClassMonikerOfManyToManyRelationSerializer.TryCreateMonikerInstance(serializationContext, reader, element, ManyToManyRelation.DomainClassId, element.Partition); if (newModelClassMonikerOfManyToManyRelation != null) { ActiveWriterSerializationBehaviorSerializationMessages.ExpectingFullFormRelationship(serializationContext, reader, typeof(ManyToManyRelation)); new ManyToManyRelation(element.Partition, new DslModeling::RoleAssignment(ManyToManyRelation.SourceDomainRoleId, element), new DslModeling::RoleAssignment(ManyToManyRelation.TargetDomainRoleId, newModelClassMonikerOfManyToManyRelation)); DslModeling::SerializationUtilities.Skip(reader); // Moniker contains no child XML elements, so just skip. } else { // Unknown element, skip. DslModeling::SerializationUtilities.Skip(reader); } } } }
/// <summary> /// Reads all instances of relationship ClassHasProperty. /// </summary> /// <remarks> /// The caller will position the reader at the open tag of the first XML element inside the relationship tag, so it can be /// either the first instance, or a bogus tag. This method will deserialize all instances and ignore all bogus tags. When the /// method returns, the reader will be positioned at the end tag of the relationship (or EOF if somehow that happens). /// </remarks> /// <param name="serializationContext">Serialization context.</param> /// <param name="element">In-memory ModelClass instance that will get the deserialized data.</param> /// <param name="reader">XmlReader to read serialized data from.</param> private static void ReadClassHasPropertyInstances(DslModeling::SerializationContext serializationContext, ModelClass element, global::System.Xml.XmlReader reader) { while (!serializationContext.Result.Failed && !reader.EOF && reader.NodeType == global::System.Xml.XmlNodeType.Element) { DslModeling::DomainClassXmlSerializer newModelPropertyOfClassHasPropertySerializer = serializationContext.Directory.GetSerializer(ModelProperty.DomainClassId); global::System.Diagnostics.Debug.Assert(newModelPropertyOfClassHasPropertySerializer != null, "Cannot find serializer for ModelProperty!"); ModelProperty newModelPropertyOfClassHasProperty = newModelPropertyOfClassHasPropertySerializer.TryCreateInstance(serializationContext, reader, element.Partition) as ModelProperty; if (newModelPropertyOfClassHasProperty != null) { element.Properties.Add(newModelPropertyOfClassHasProperty); DslModeling::DomainClassXmlSerializer targetSerializer = serializationContext.Directory.GetSerializer (newModelPropertyOfClassHasProperty.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert (targetSerializer != null, "Cannot find serializer for " + newModelPropertyOfClassHasProperty.GetDomainClass().Name + "!"); targetSerializer.Read(serializationContext, newModelPropertyOfClassHasProperty, reader); } else { global::System.Type typeofClassHasProperty = typeof(ClassHasProperty); DslModeling::DomainRelationshipXmlSerializer newClassHasPropertySerializer = serializationContext.Directory.GetSerializer(ClassHasProperty.DomainClassId) as DslModeling::DomainRelationshipXmlSerializer; global::System.Diagnostics.Debug.Assert(newClassHasPropertySerializer != null, "Cannot find serializer for ClassHasProperty!"); ClassHasProperty newClassHasProperty = newClassHasPropertySerializer.TryCreateInstance (serializationContext, reader, element.Partition) as ClassHasProperty; if (newClassHasProperty != null) { if (newClassHasProperty.GetType() == typeofClassHasProperty) { // The relationship should be serialized in short-form. ActiveWriterSerializationBehaviorSerializationMessages.ExpectingShortFormRelationship(serializationContext, reader, typeof(ClassHasProperty)); } DslModeling::DomainRoleInfo.SetRolePlayer (newClassHasProperty, ClassHasProperty.ModelClassDomainRoleId, element); DslModeling::DomainClassXmlSerializer targetSerializer = serializationContext.Directory.GetSerializer (newClassHasProperty.GetDomainClass().Id); global::System.Diagnostics.Debug.Assert (targetSerializer != null, "Cannot find serializer for " + newClassHasProperty.GetDomainClass().Name + "!"); targetSerializer.Read(serializationContext, newClassHasProperty, reader); } else { // Unknown element, skip DslModeling::SerializationUtilities.Skip(reader); } } } }
/// <summary> /// This method deserializes all child model elements. /// </summary> /// <remarks> /// The caller will position the reader at the open tag of the first child XML element to deserialized. /// This method will read as many child elements as it can. It returns under three circumstances: /// 1) When an unknown child XML element is encountered. In this case, this method will position the reader at the /// open tag of the unknown element. This implies the if the first child XML element is unknown, this method /// should return immediately and do nothing. /// 2) When all child XML elemnets are read. In this case, the reader will be positioned at the end tag of the parent element. /// 3) EOF. /// </remarks> /// <param name="serializationContext">Serialization context.</param> /// <param name="reader">XmlReader to read serialized data from.</param> /// <param name="element">In-memory ModelClass instance that will get the deserialized data.</param> private static void ReadChildElements(DslModeling::SerializationContext serializationContext, ModelClass element, global::System.Xml.XmlReader reader) { while (!serializationContext.Result.Failed && !reader.EOF && reader.NodeType == global::System.Xml.XmlNodeType.Element) { switch (reader.LocalName) { case "targets": // Relationship "ManyToOneRelation" if (reader.IsEmptyElement) { // No instance of this relationship, just skip DslModeling::SerializationUtilities.Skip(reader); } else { DslModeling::SerializationUtilities.SkipToFirstChild(reader); // Skip the open tag of <targets> ReadManyToOneRelationInstances(serializationContext, element, reader); DslModeling::SerializationUtilities.Skip(reader); // Skip the close tag of </targets> } break; case "properties": // Relationship "ClassHasProperty" if (reader.IsEmptyElement) { // No instance of this relationship, just skip DslModeling::SerializationUtilities.Skip(reader); } else { DslModeling::SerializationUtilities.SkipToFirstChild(reader); // Skip the open tag of <properties> ReadClassHasPropertyInstances(serializationContext, element, reader); DslModeling::SerializationUtilities.Skip(reader); // Skip the close tag of </properties> } break; case "manyToManyTargets": // Relationship "ManyToManyRelation" if (reader.IsEmptyElement) { // No instance of this relationship, just skip DslModeling::SerializationUtilities.Skip(reader); } else { DslModeling::SerializationUtilities.SkipToFirstChild(reader); // Skip the open tag of <manyToManyTargets> ReadManyToManyRelationInstances(serializationContext, element, reader); DslModeling::SerializationUtilities.Skip(reader); // Skip the close tag of </manyToManyTargets> } break; case "oneToOneTarget": // Relationship "OneToOneRelation" if (reader.IsEmptyElement) { // No instance of this relationship, just skip DslModeling::SerializationUtilities.Skip(reader); } else { DslModeling::SerializationUtilities.SkipToFirstChild(reader); // Skip the open tag of <oneToOneTarget> ReadOneToOneRelationInstance(serializationContext, element, reader); DslModeling::SerializationUtilities.Skip(reader); // Skip the close tag of </oneToOneTarget> } break; default: return; // Don't know this element. } } }
private void PopulateClass(ModelClass cls, IDbConnection connection, IDbHelper helper) { if (cls != null && connection != null) { // Relations to this class (this class has the primary key) List<Relation> relationsTo = helper.GetPKRelations(cls); // If the other side of the relation (FK part) is not in our model, we won't // need the relation at all _manager.FilterPKRelations(relationsTo); // Relations from this class (this class has the foreign key) List<Relation> relationsFrom = helper.GetFKRelations(cls); // If the other side of the relation (PK part) is not in our model, we won't // need the relation at all _manager.FilterFKRelations(relationsFrom); // Properties List<Column> columns = helper.GetProperties(cls); if (columns != null && columns.Count > 0) { List<Column> secondPass = new List<Column>(); foreach(Column column in columns) { // We'll handle primary and foreigns later. First, we'll create ordinary properties. if (column.Primary || (column.ForeignConstraints.Count > 0 && (Relation.GetCountOfMatchingRelations(relationsTo, column.ForeignConstraints) > 0 || Relation.GetCountOfMatchingRelations(relationsFrom, column.ForeignConstraints) > 0) ) ) { secondPass.Add(column); } else { _manager.NewProperty(cls, column).ColumnType = helper.GetNHibernateType(column.DataType); } } // Keys List<Column> primaryKeys = null; if (secondPass.Count > 0) { primaryKeys = Column.FindPrimaryKeys(secondPass); if (primaryKeys != null && primaryKeys.Count > 0) { // Create primary and composite keys if (primaryKeys.Count == 1) { ModelProperty keyProperty = _manager.NewPrimaryKey(cls, primaryKeys[0]); keyProperty.ColumnType = helper.GetNHibernateType(primaryKeys[0].DataType); SetGenerator(keyProperty); } else { string keyClassName = cls.Name + Common.CompositeClassNameSuffix; foreach(Column key in primaryKeys) { ModelProperty keyProperty = _manager.NewCompositeKey(cls, key, keyClassName); keyProperty.ColumnType = helper.GetNHibernateType(key.DataType); SetGenerator(keyProperty); } } } } if (relationsTo != null && relationsTo.Count > 0) { foreach(Relation relation in relationsTo) { relation.PrimaryModelClass = cls; } } _relations.AddRange(relationsTo); if (relationsFrom != null && relationsFrom.Count > 0) { foreach(Relation relation in relationsFrom) { relation.ForeignModelClass = cls; } _relations.AddRange(relationsFrom); // To define many to many and one to one, we need to know the pattern of foreign keys. if (primaryKeys != null && primaryKeys.Count > 0) { foreach(Column key in primaryKeys) { Relation relation = Relation.GetForeginColumn(relationsFrom, key); if (relation != null) { relation.IsForeignColumnPrimary = true; } } } } } } }
public bool ImplementsINotifyPropertyChanged() { return(ModelClass != null ? ModelClass.DoesImplementINotifyPropertyChanged() : NestedClass.DoesImplementINotifyPropertyChanged()); }