Skip to content

Instantly share code, notes, and snippets.

@santanaguy

santanaguy/EF.cs Secret

Last active January 4, 2016 07:19
//Some change may be needed here, depending on your version
public static XNamespace edmx = "http://schemas.microsoft.com/ado/2009/11/edmx";
public static XNamespace xmlnsssdl = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl";
public static XNamespace xmlnsedm = "http://schemas.microsoft.com/ado/2009/11/edm";
public static XNamespace xmlnscs = "http://schemas.microsoft.com/ado/2009/11/mapping/cs";
void Main()
{
string rootDir = @"C:\Users\Admin\Documents\visual studio 2013\Projects\ConsoleApplication2\ConsoleApplication2";
string BackupDestination = @"C:\Users\Admin\Documents\visual studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\Backup";
string resultFilePath = rootDir + @"\ReportServer.edmx";
string[] files = new string[]
{
rootDir + @"\SimpleAccount.edmx",
};
Backup(rootDir, BackupDestination);
MergeEDMX(files, resultFilePath);
ReplacePrefixes(resultFilePath);
ReorderNavigationProperties(resultFilePath);
}
private static void MergeEDMX(string[] files, string ResultFile)
{
Console.WriteLine ("Merging EDMX");
foreach (string file in files)
{
XDocument doc = XDocument.Load(file);
XDocument docresult = XDocument.Load(ResultFile);
//SSDL
Console.WriteLine ("Merging SSDL");
MergeNodes(docresult.Root.Descendants(xmlnsssdl + "EntityContainer").First(),
doc.Root.Descendants(xmlnsssdl + "EntityContainer").Elements(),
docresult.Root.Descendants(xmlnsssdl + "EntityContainer").Elements(),
(x,y) => x.Attribute("Name").Value == y.Attribute("Name").Value);
MergeNodes(docresult.Root.Descendants(xmlnsssdl + "Schema").First(),
doc.Root.Descendants(xmlnsssdl + "Schema").Elements().Where(x=> x.Name != xmlnsssdl + "EntityContainer"),
docresult.Root.Descendants(xmlnsssdl + "Schema").Elements().Where(x=> x.Name != xmlnsssdl + "EntityContainer"),
(x,y) => x.Attribute("Name").Value == y.Attribute("Name").Value);
Console.WriteLine ("Done SSDL");
//CSDL
Console.WriteLine ("Merging CSDL");
MergeNodes(docresult.Root.Descendants(xmlnsedm + "EntityContainer").First(),
doc.Root.Descendants(xmlnsedm + "EntityContainer").Elements(),
docresult.Root.Descendants(xmlnsedm + "EntityContainer").Elements(),
(x,y) => x.Attribute("Name").Value == y.Attribute("Name").Value);
//Import NavigationProperties. First we go to already existant entities (OldEntities) to read existing NavProp
//Then we import those Elements to the new entity (NewEntity) in the loop
var OldEntities = docresult.Root.Descendants(xmlnsedm + "EntityType");
var NewEntities = doc.Root.Descendants(xmlnsedm + "EntityType");
foreach (var NewEntity in NewEntities)
{
var OldEntity = OldEntities.FirstOrDefault(x=> x.Attribute("Name").Value == NewEntity.Attribute("Name").Value);
if (OldEntity == null)
continue;
NewEntity.Add(OldEntity
.Elements(xmlnsedm + "NavigationProperty")
.Where(x=> x.Attribute("Relationship").Value.Contains(".LNK_")));
}
NewEntities = NewEntities.Union(doc.Root.Descendants(xmlnsedm + "Schema").Elements().Where(x=> x.Name != xmlnsedm + "EntityContainer"));
//
//Merge the itens inside the Schema (except EntityContainer)
MergeNodes(docresult.Root.Descendants(xmlnsedm + "Schema").First(),
NewEntities.ToList(),
docresult.Root.Descendants(xmlnsedm + "Schema").Elements().Where(x=> x.Name != xmlnsedm + "EntityContainer"),
(x,y) => x.Attribute("Name").Value == y.Attribute("Name").Value);
Console.WriteLine ("Done CSDL");
//C-S
Console.WriteLine ("Merging C-S");
//Merge the itens inside EntityContainer in the C-S layer
MergeNodes(docresult.Root.Descendants(xmlnscs + "EntityContainerMapping").First(),
doc.Root.Descendants(xmlnscs + "EntitySetMapping"),
docresult.Root.Descendants(xmlnscs + "EntitySetMapping"),
(x,y) => x.Attribute("Name").Value == y.Attribute("Name").Value);
//Merge the functions (requires different attribute comparing)
MergeNodes(docresult.Root.Descendants(xmlnscs + "EntityContainerMapping").First(),
doc.Root.Descendants(xmlnscs + "FunctionImportMapping"),
docresult.Root.Descendants(xmlnscs + "FunctionImportMapping"),
(x,y) => x.Attribute("FunctionImportName").Value == y.Attribute("FunctionImportName").Value);
Console.WriteLine ("Done C-S");
docresult.Save(ResultFile);
}
Console.WriteLine("Done Merging");
}
//Deletes old nodes that exist in a ParentTarget and in the NewChilds when the comparer returns true
private static void MergeNodes(XElement ParentTarget, IEnumerable<XElement> NewChilds, IEnumerable<XElement> OldChilds, Func<XElement, XElement, bool> ChildComparer)
{
(from OldFunc in OldChilds
from NewFunc in NewChilds
where ChildComparer(OldFunc, NewFunc)
select OldFunc).Remove();
//Add new functions
ParentTarget.Add(NewChilds);
}
//Reorders the navigation properties of an EDMX
private void ReorderNavigationProperties(string EDMXFilePath)
{
Console.WriteLine ("Reordering navigation properties");
XDocument doc = XDocument.Load(EDMXFilePath);
foreach (var Entity in doc.Root.Descendants(edmx + "Runtime")
.Descendants(edmx + "ConceptualModels")
.Descendants(xmlnsedm + "Schema")
.Descendants(xmlnsedm + "EntityType"))
{
Entity.ReplaceNodes(
Entity.Descendants()
.Where (x => x.Parent == Entity) //Descendentes directos
.OrderBy (x => x.Name == xmlnsedm + "NavigationProperty" ? x.Attribute("Name").Value : "a" ));
}
doc.Save(EDMXFilePath);
Console.WriteLine("Done");
}
//Replace the prefixes of the other models.
private void ReplacePrefixes(string FilePath)
{
Console.WriteLine ("Replacing database prefixes");
string CorrectPrefix = "Model";
var text = File.ReadAllText(FilePath);
text = text.Replace("SimpleAccountModel", CorrectPrefix);
File.WriteAllText(FilePath, text);
Console.WriteLine ("Done");
}
public void Backup(string source, string destination)
{
string DoBackups;
Console.WriteLine ("Do backups first? y/n");
do
{
DoBackups = Console.ReadLine();
} while (DoBackups != "y" && DoBackups != "n");
if (DoBackups == "y")
{
Console.WriteLine ("Performing backups");
DoBackup(source, destination);
Console.WriteLine ("Done");
}
else
Console.WriteLine ("Ignoring backups...");
}
//Backs up all .edmx and .Designer.cs in the Source directory.
public void DoBackup(string Source, string Destination)
{
DirectoryInfo srcDir = new DirectoryInfo(Source);
DirectoryInfo dstDir = new DirectoryInfo(Destination);
var files = from file in srcDir.GetFiles()
where file.Extension == ".edmx"
|| file.Name.Contains(".Designer.cs")
select file;
foreach (FileInfo FileName in files)
{
if (!dstDir.Exists)
dstDir.Create();
System.IO.File.Copy(FileName.FullName, dstDir.FullName + "\\" + FileName.Name, true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment