private static void BuildEntity(string[] debugViewLines, string entityName, int i, DebugViewParserResult result, List <string> properties, List <string> propertyLinks, string line, ref bool inProperties) { if (!string.IsNullOrEmpty(entityName)) { var isAbstract = false; var baseClass = string.Empty; string changeTrackingStrategy = "ChangeTrackingStrategy.Snapshot"; if (!string.IsNullOrEmpty(line)) { var parts = line.Trim().Split(' ').ToList(); isAbstract = parts.Contains("Abstract"); if (parts.Contains("Base:")) { baseClass = parts[parts.IndexOf("Base:") + 1]; } changeTrackingStrategy = parts.FirstOrDefault(p => p.StartsWith("ChangeTrackingStrategy.", StringComparison.Ordinal)); } if (string.IsNullOrEmpty(changeTrackingStrategy)) { changeTrackingStrategy = "ChangeTrackingStrategy.Snapshot"; } var annotations = GetEntityAnnotations(i, debugViewLines); var annotation = string.Join(Environment.NewLine, annotations); result.Nodes.Add( $"<Node Id = \"{entityName}\" Label=\"{entityName}\" Name=\"{entityName}\" BaseClass=\"{baseClass}\" IsAbstract=\"{isAbstract}\" ChangeTrackingStrategy=\"{changeTrackingStrategy}\" Annotations=\"{annotation}\" Category=\"EntityType\" Group=\"Expanded\" />"); result.Links.Add( $"<Link Source = \"IModel\" Target=\"{entityName}\" Category=\"Contains\" />"); result.Nodes.AddRange(properties.Distinct()); result.Links.AddRange(propertyLinks.Distinct()); properties.Clear(); propertyLinks.Clear(); } inProperties = false; }
public static DebugViewParserResult Parse(string[] debugViewLines, string dbContextName) { if (debugViewLines == null) { throw new ArgumentNullException(nameof(debugViewLines)); } var result = new DebugViewParserResult(); var modelAnnotated = false; var productVersion = string.Empty; var modelAnnotations = new StringBuilder(); var modelPropertyAccessMode = "PropertyAccessMode.Default"; var changeTrackingStrategy = "ChangeTrackingStrategy.Snapshot"; foreach (var line in debugViewLines) { if (line.StartsWith("Model:", StringComparison.Ordinal)) { var props = line.Trim().Split(' ').ToList(); if (props.Count > 0) { changeTrackingStrategy = props.FirstOrDefault(p => p.StartsWith("ChangeTrackingStrategy.", StringComparison.Ordinal)); if (string.IsNullOrEmpty(changeTrackingStrategy)) { changeTrackingStrategy = "ChangeTrackingStrategy.Snapshot"; } modelPropertyAccessMode = GetPropertyAccessMode(props); } } if (line.StartsWith("Annotations:", StringComparison.Ordinal)) { modelAnnotated = true; } if (modelAnnotated) { if (line.TrimStart().StartsWith("ProductVersion: ", StringComparison.Ordinal)) { productVersion = line.Trim().Split(' ')[1]; } if (!line.TrimStart().StartsWith("ProductVersion: ", StringComparison.Ordinal) && !line.TrimStart().StartsWith("Annotations:", StringComparison.Ordinal)) { modelAnnotations.AppendLine(line.Trim()); } } } result.Nodes.Add( $"<Node Id=\"IModel\" Label=\"{dbContextName}\" ChangeTrackingStrategy=\"{changeTrackingStrategy}\" PropertyAccessMode=\"{modelPropertyAccessMode}\" ProductVersion=\"{productVersion}\" Annotations=\"{modelAnnotations.ToString().Trim()}\" Category=\"Model\" Group=\"Expanded\" />"); var entityName = string.Empty; var properties = new List <string>(); var propertyLinks = new List <string>(); var inProperties = false; var inOtherProperties = false; var i = -1; foreach (var line in debugViewLines) { i++; if (line.TrimStart().StartsWith("EntityType:", StringComparison.Ordinal)) { entityName = System.Security.SecurityElement.Escape(line.Trim().Split(' ')[1]); BuildEntity(debugViewLines, entityName, i, result, properties, propertyLinks, line, ref inProperties); } if (line.TrimStart().StartsWith("Properties:", StringComparison.Ordinal)) { inProperties = true; inOtherProperties = false; } if (!string.IsNullOrEmpty(entityName) && inProperties) { if (line.StartsWith(" Keys:", StringComparison.Ordinal) || line.StartsWith(" Navigations:", StringComparison.Ordinal) || line.StartsWith(" Annotations:", StringComparison.Ordinal) || line.StartsWith(" Foreign keys:", StringComparison.Ordinal)) { inOtherProperties = true; continue; } if (line.StartsWith(" ", StringComparison.Ordinal) && !inOtherProperties) { var annotations = GetAnnotations(i, debugViewLines); var navigations = GetNavigations(i, debugViewLines); var foreignKeysFragment = GetForeignKeys(i, debugViewLines); if (line.StartsWith(" Annotations:", StringComparison.Ordinal) || line.StartsWith(" ", StringComparison.Ordinal)) { continue; } var annotation = string.Join(Environment.NewLine, annotations); var foundLine = line.Replace("(no field, ", "(nofield,"); foundLine = foundLine.Replace(", ", ","); var props = foundLine.Trim().Split(' ').ToList(); var name = props[0]; var field = GetTypeValue(props[1], true); var type = GetTypeValue(props[1], false); props.RemoveRange(0, 2); var isRequired = props.Contains("Required"); var isIndexed = props.Contains("Index"); var isPrimaryKey = props.Contains("PK"); var isForeignKey = props.Contains("FK"); var isShadow = props.Contains("Shadow"); var isAlternateKey = props.Contains("AlternateKey"); var isConcurrency = props.Contains("Concurrency"); var isUnicode = !props.Contains("Ansi"); var beforeSaveBehavior = "PropertySaveBehavior.Save"; if (props.Contains("BeforeSave:PropertySaveBehavior.Ignore")) { beforeSaveBehavior = "PropertySaveBehavior.Ignore"; } if (props.Contains("BeforeSave:PropertySaveBehavior.Throw")) { beforeSaveBehavior = "PropertySaveBehavior.Throw"; } var afterSaveBehavior = "PropertySaveBehavior.Save"; if (props.Contains("AfterSave:PropertySaveBehavior.Ignore")) { afterSaveBehavior = "PropertySaveBehavior.Ignore"; } if (props.Contains("AfterSave:PropertySaveBehavior.Throw")) { afterSaveBehavior = "PropertySaveBehavior.Throw"; } string propertyAccesMode = GetPropertyAccessMode(props); var maxLength = props.FirstOrDefault(p => p.StartsWith("MaxLength", StringComparison.Ordinal)); if (string.IsNullOrEmpty(maxLength)) { maxLength = "None"; } else { maxLength = maxLength.Replace("MaxLength", string.Empty); } var valueGenerated = props.FirstOrDefault(p => p.StartsWith("ValueGenerated.", StringComparison.Ordinal)) ?? "None"; var category = "Property Required"; if (!isRequired) { category = "Property Optional"; } if (isForeignKey) { category = "Property Foreign"; } if (isPrimaryKey) { category = "Property Primary"; } properties.Add( $"<Node Id = \"{entityName}.{name}\" Label=\"{name}\" Name=\"{name}\" Category=\"{category}\" Type=\"{type}\" MaxLength=\"{maxLength}\" Field=\"{field}\" PropertyAccessMode=\"{propertyAccesMode}\" BeforeSaveBehavior=\"{beforeSaveBehavior}\" AfterSaveBehavior=\"{afterSaveBehavior}\" Annotations=\"{annotation}\" IsPrimaryKey=\"{isPrimaryKey}\" IsForeignKey=\"{isForeignKey}\" IsRequired=\"{isRequired}\" IsIndexed=\"{isIndexed}\" IsShadow=\"{isShadow}\" IsAlternateKey=\"{isAlternateKey}\" IsConcurrencyToken=\"{isConcurrency}\" IsUnicode=\"{isUnicode}\" ValueGenerated=\"{valueGenerated}\" />"); var navigationResult = ParseNavigations(navigations, entityName); properties.AddRange(navigationResult.Item1); propertyLinks.AddRange(navigationResult.Item2); propertyLinks.Add($"<Link Source = \"{entityName}\" Target=\"{entityName}.{name}\" Category=\"Contains\" />"); propertyLinks.AddRange(ParseForeignKeys(foreignKeysFragment)); } } } BuildEntity(debugViewLines, entityName, i, result, properties, propertyLinks, null, ref inProperties); return(result); }