Skip to content
This repository has been archived by the owner on Jun 14, 2024. It is now read-only.

Commit

Permalink
Support VS's EDMX Editor.
Browse files Browse the repository at this point in the history
Multi schemata.
1 -> 0..1
Bug multi Role and so on.
  • Loading branch information
kenjiuno committed Oct 23, 2014
1 parent 2db9baa commit 818cd4e
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 31 deletions.
146 changes: 118 additions & 28 deletions EdmGenModelGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Collections.Generic;

namespace EdmGen06 {
public class EdmGenModelGen : EdmGenBase {
Expand Down Expand Up @@ -157,14 +158,37 @@ public void ModelGen2(String connectionString, String providerName, String typeP

XElement mssdl, mcsdl, mmsl;
XDocument mEdmx = new XDocument(); // XDocument: ModelGen edmx
mEdmx.Add(new XElement(xEDMX + "Edmx",
new XAttribute("Version", yver.ToString(2)),
new XElement(xEDMX + "Runtime",
mssdl = new XElement(xEDMX + "StorageModels"),
mcsdl = new XElement(xEDMX + "ConceptualModels"),
mmsl = new XElement(xEDMX + "Mappings")
mEdmx.Add(
new XElement(xEDMX + "Edmx",
new XAttribute("Version", yver.ToString(2)),
new XElement(xEDMX + "Runtime",
mssdl = new XElement(xEDMX + "StorageModels"),
mcsdl = new XElement(xEDMX + "ConceptualModels"),
mmsl = new XElement(xEDMX + "Mappings")
),
new XElement(xEDMX + "Designer",
new XElement(xEDMX + "Connection"
),
new XElement(xEDMX + "Options",
new XElement(xEDMX + "DesignerInfoPropertySet",
new XElement(xEDMX + "DesignerProperty",
new XAttribute("Name", "EnablePluralization"),
new XAttribute("Value", "False")
),
new XElement(xEDMX + "DesignerProperty",
new XAttribute("Name", "IncludeForeignKeysInModel"),
new XAttribute("Value", "True")
),
new XElement(xEDMX + "DesignerProperty",
new XAttribute("Name", "UseLegacyProvider"),
new XAttribute("Value", "True")
)
)
),
new XElement(xEDMX + "Diagrams"
)
)
)
)
);

trace.TraceEvent(TraceEventType.Information, 101, "Getting SchemaInformation");
Expand Down Expand Up @@ -206,14 +230,39 @@ public void ModelGen2(String connectionString, String providerName, String typeP
);
mslMapping.Add(mslEntityContainerMapping);

var vecTableOrView = Context.Tables.Cast<TableOrView>().Union(Context.Views.Cast<TableOrView>());
var allTableOrView = Context.Tables.Cast<TableOrView>().Union(Context.Views.Cast<TableOrView>()).ToArray();

nut.localTypes = vecTableOrView.Select(p => p.Name).ToArray();
nut.localTypes = allTableOrView.Select(p => p.Name).ToArray();

foreach (var dbt in vecTableOrView) {
trace.TraceEvent(TraceEventType.Information, 101, "{2}: {0}.{1}", dbt.SchemaName, dbt.Name, (dbt is Table) ? "Table" : "View");
List<TableOrView> processTableOrView = allTableOrView.Where(dbt => dbt.SchemaName == targetSchema).ToList();

while (true) {
bool more = false;
foreach (var dbco in Context.TableConstraints.OfType<ForeignKeyConstraint>()) {
dbco.ForeignKeys.Load();
foreach (var dbfk in dbco.ForeignKeys) {
dbfk.FromColumnReference.Load();
dbfk.FromColumn.ParentReference.Load();

{
var dbt = dbfk.FromColumn.Parent;
if (!processTableOrView.Contains(dbt) && allTableOrView.Contains(dbt)) { processTableOrView.Add(dbt); more |= true; }
}

if (dbt.SchemaName != targetSchema) continue;
dbfk.ToColumnReference.Load();
dbfk.ToColumn.ParentReference.Load();

{
var dbt = dbfk.ToColumn.Parent;
if (!processTableOrView.Contains(dbt) && allTableOrView.Contains(dbt)) { processTableOrView.Add(dbt); more |= true; }
}
}
}
if (!more) break;
}

foreach (var dbt in processTableOrView) {
trace.TraceEvent(TraceEventType.Information, 101, "{2}: {0}.{1}", dbt.SchemaName, dbt.Name, (dbt is Table) ? "Table" : "View");

XElement ssdlEntitySet = new XElement(xSSDL + "EntitySet"
, new XAttribute("Name", nut.SsdlEntitySet(dbt))
Expand Down Expand Up @@ -258,11 +307,12 @@ public void ModelGen2(String connectionString, String providerName, String typeP
XElement csdlKey = null;
bool hasKey = false; // http://social.msdn.microsoft.com/Forums/en-US/94c227d3-3764-45b2-8c6b-e45b6cc8e169/keyless-object-workaround
bool hasId = dbt.Columns.Any(p => p.IsIdentity || p.Constraints.OfType<PrimaryKeyConstraint>().Any());
if (!dbt.Columns.IsLoaded) dbt.Columns.Load();
dbt.Columns.Load();
foreach (var dbc in dbt.Columns) {
trace.TraceEvent(TraceEventType.Information, 101, " TableColumn: {0}", dbc.Name);

bool isIdGen = dbc.IsIdentity;
dbc.Constraints.Load();
bool isId = isIdGen || dbc.Constraints.OfType<PrimaryKeyConstraint>().Any() || (hasId ? false : !dbc.IsNullable);

String ssdlName;
Expand Down Expand Up @@ -353,8 +403,6 @@ public void ModelGen2(String connectionString, String providerName, String typeP
foreach (var dbco in Context.TableConstraints.OfType<ForeignKeyConstraint>()) {
trace.TraceEvent(TraceEventType.Information, 101, "Constraint: {0}", dbco.Name);

if (dbco.Parent.SchemaName != targetSchema) continue;

// ssdl
var ssdlAssociationSet = new XElement(xSSDL + "AssociationSet"
, new XAttribute("Name", nut.SsdlAssociationSet(dbco))
Expand Down Expand Up @@ -385,11 +433,33 @@ public void ModelGen2(String connectionString, String providerName, String typeP
var csdlReferentialConstraint = new XElement(xCSDL + "ReferentialConstraint"
);

if (!dbco.ForeignKeys.IsLoaded) dbco.ForeignKeys.Load();
dbco.ForeignKeys.Load();

foreach (var dbfk in dbco.ForeignKeys) {
dbfk.FromColumnReference.Load();
dbfk.FromColumn.ParentReference.Load();
dbfk.FromColumn.Constraints.Load();
dbfk.ToColumnReference.Load();
dbfk.ToColumn.ParentReference.Load();
dbfk.ToColumn.Constraints.Load();

int pkcFrom = 0;
foreach (var dbpk in dbfk.FromColumn.Constraints.OfType<PrimaryKeyConstraint>()) {
dbpk.Columns.Load();
pkcFrom = dbpk.Columns.Count;
break;
}
int pkcTo = 0;
foreach (var dbpk in dbfk.ToColumn.Constraints.OfType<PrimaryKeyConstraint>()) {
dbpk.Columns.Load();
pkcTo = dbpk.Columns.Count;
break;
}
bool same = (pkcFrom == dbco.ForeignKeys.Count && dbco.ForeignKeys.Count == pkcTo);

Addfkc(csdlSchema, dbfk, dbfk.ToColumn, dbfk.FromColumn, false, dbfk.FromColumn.IsNullable ? "0..1" : "1"
, ssdlAssociationSet, ssdlAssociation, ssdlReferentialConstraint, csdlAssociationSet, csdlAssociation, csdlReferentialConstraint);
Addfkc(csdlSchema, dbfk, dbfk.FromColumn, dbfk.ToColumn, true, "*"
Addfkc(csdlSchema, dbfk, dbfk.FromColumn, dbfk.ToColumn, true, same ? "0..1" : "*"
, ssdlAssociationSet, ssdlAssociation, ssdlReferentialConstraint, csdlAssociationSet, csdlAssociation, csdlReferentialConstraint);
}

Expand Down Expand Up @@ -581,6 +651,26 @@ public void ModelGen2(String connectionString, String providerName, String typeP
}
}

XElement Once(XElement parent, XElement newc) {
foreach (XElement curc in parent.Elements()) {
if (Strify(curc).Equals(Strify(newc)))
return curc;
}

parent.Add(newc);
return newc;
}

String Strify(XElement e1) {
StringWriter wr = new StringWriter();
wr.WriteLine(e1.Name);
foreach (XAttribute att in e1.Attributes().OrderBy(p => "" + p.Name)) {
wr.WriteLine(att.Name);
wr.WriteLine(att.Value);
}
return wr.ToString();
}

private void Addfkc(XElement csdlSchema, ForeignKey dbfk, Column dbfkc, Column dbfkc2, bool isMulti, String multiplicity
, XElement ssdlAssociationSet, XElement ssdlAssociation, XElement ssdlReferentialConstraint
, XElement csdlAssociationSet, XElement csdlAssociation, XElement csdlReferentialConstraint
Expand All @@ -603,48 +693,48 @@ private void Addfkc(XElement csdlSchema, ForeignKey dbfk, Column dbfkc, Column d
, new XAttribute("Role", nut.SsdlEntitySet(dbfkc.Parent))
, new XAttribute("EntitySet", nut.SsdlEntitySet(dbfkc.Parent))
);
ssdlAssociationSet.Add(ssdlasEnd);
ssdlasEnd = Once(ssdlAssociationSet, ssdlasEnd);

var ssdlaEnd = new XElement(xSSDL + "End"
, new XAttribute("Role", nut.SsdlEntitySet(dbfkc.Parent))
, new XAttribute("Type", nut.SsdlEntityTypeRef(dbfkc.Parent))
, new XAttribute("Multiplicity", multiplicity)
);
ssdlAssociation.Add(ssdlaEnd);
ssdlaEnd = Once(ssdlAssociation, ssdlaEnd);

var ssdlarc = new XElement(xSSDL + (isMulti ? "Dependent" : "Principal")
, new XAttribute("Role", nut.SsdlEntitySet(dbfkc.Parent))
);
ssdlReferentialConstraint.Add(ssdlarc);
ssdlarc = Once(ssdlReferentialConstraint, ssdlarc);

var ssdlPropertyRef = new XElement(xSSDL + "PropertyRef"
, new XAttribute("Name", nut.SsdlProp(dbfkc))
);
ssdlarc.Add(ssdlPropertyRef);
ssdlPropertyRef = Once(ssdlarc, ssdlPropertyRef);

// csdl
var csdlasEnd = new XElement(xCSDL + "End"
, new XAttribute("Role", nut.CsdlEntitySet(dbfkc.Parent))
, new XAttribute("EntitySet", nut.CsdlEntitySet(dbfkc.Parent))
);
csdlAssociationSet.Add(csdlasEnd);
csdlasEnd = Once(csdlAssociationSet, csdlasEnd);

var csdlaEnd = new XElement(xCSDL + "End"
, new XAttribute("Role", nut.CsdlEntitySet(dbfkc.Parent))
, new XAttribute("Type", nut.CsdlEntityTypeRef(dbfkc.Parent))
, new XAttribute("Multiplicity", multiplicity)
);
csdlAssociation.Add(csdlaEnd);
csdlaEnd = Once(csdlAssociation, csdlaEnd);

var csdlarc = new XElement(xCSDL + (isMulti ? "Dependent" : "Principal")
, new XAttribute("Role", nut.CsdlEntitySet(dbfkc.Parent))
);
csdlReferentialConstraint.Add(csdlarc);
csdlarc = Once(csdlReferentialConstraint, csdlarc);

var csdlPropertyRef = new XElement(xCSDL + "PropertyRef"
, new XAttribute("Name", nut.CsdlProp(dbfkc))
);
csdlarc.Add(csdlPropertyRef);
csdlPropertyRef = Once(csdlarc, csdlPropertyRef);

var csdlNavigationProperty = new XElement(xCSDL + "NavigationProperty"
, new XAttribute("Name", nut.CsdlEntityType(dbfkc.Parent))
Expand All @@ -656,7 +746,7 @@ private void Addfkc(XElement csdlSchema, ForeignKey dbfk, Column dbfkc, Column d
.Where(p => p.Attribute("Name").Value == nut.CsdlEntityType(dbfkc2.Parent))
.FirstOrDefault();
if (csdlEntityType != null) {
csdlEntityType.Add(csdlNavigationProperty);
csdlNavigationProperty = Once(csdlEntityType, csdlNavigationProperty);
}
}

Expand All @@ -670,8 +760,8 @@ class Nameut {

public String SsdlNs() { return String.Format("{0}", targetSchema); }
public String SsdlContainer() { return String.Format("{0}StoreContainer", modelName); }
public String SsdlEntitySet(TableOrView dbt) { return dbt.Name; }
public String SsdlEntityType(TableOrView dbt) { return String.Format("{0}", dbt.Name); }
public String SsdlEntitySet(TableOrView dbt) { return String.Format("{1}", dbt.SchemaName, dbt.Name); }
public String SsdlEntityType(TableOrView dbt) { return String.Format("{0}_{1}", dbt.SchemaName, dbt.Name); }
public String SsdlEntityTypeRef(TableOrView dbt) { return String.Format("{0}.{1}", SsdlNs(), SsdlEntityType(dbt)); }

public String SsdlProp(Column dbc) { return dbc.Name; }
Expand Down
6 changes: 3 additions & 3 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を
// 既定値にすることができます:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.8.0.0")]
[assembly: AssemblyFileVersion("0.8.0.0")]
[assembly: AssemblyInformationalVersion("0.8.0.0")]
[assembly: AssemblyVersion("0.9.0.0")]
[assembly: AssemblyFileVersion("0.9.0.0")]
[assembly: AssemblyInformationalVersion("0.9.0.0")]

3 comments on commit 818cd4e

@janslavsky
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello,

nice job but wehn I am trying to generate model for my database I am getting an expcetion below.
In my postgresql database I have an unaccent extension installed.
Hope I will be able to generate my model soon with your tool.

Thanks

EdmGen06 Information: 101 : Parameter: x
EdmGen06 Information: 101 : Parameter: x
EdmGen06 Information: 101 : Parameter: x
EdmGen06 Information: 101 : Function: public.tgf_t_diagnosis_rep_out
EdmGen06 Information: 101 : Function: public.unaccent_init
EdmGen06 Information: 101 : Parameter: x

Unhandled Exception: System.InvalidOperationException: The parent is missing.
at System.Xml.Linq.XNode.AddAfterSelf(Object content)
at EdmGen06.EdmGenModelGen.ModelGen2(String connectionString, String provider
Name, String typeProviderServices, String modelName, String targetSchema, Versio
n yver) in h:\Dev\EdmGen06\EdmGenModelGen.cs:line 559
at EdmGen06.Program.Main(String[] args) in h:\Dev\EdmGen06\Program.cs:line 19

@kenjiuno
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @janslavsky

Thank you for the detail report!

I'll check the on going problem which seems to be caused by the unaccent extension.

@kenjiuno
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @janslavsky

Your problem should be fixed now!
Please try the new release:
https://github.com/kenjiuno/EdmGen06/releases

Thanks.
kenji uno

Please sign in to comment.