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

Commit

Permalink
Fixed some edge cases in DLL import that were causing failures
Browse files Browse the repository at this point in the history
  • Loading branch information
msawczyn committed May 28, 2021
1 parent 712fb29 commit fd10351
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 17 deletions.
7 changes: 2 additions & 5 deletions VSMarketplace blurb.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ It's an opinionated code generator, adding a new file type (.efmodel) that allow

<img src="https://msawczyn.github.io/EFDesigner/images/Designer.jpg">

While giving you complete control over how the code is generated you'll be able to create, out of the box, sophisticated, consistent and **correct** Entity Framework code that can be regenerated when your model changes. And, since the code is written using partial classes, any additions you make to your generated code are retained across subsequent generations.
The designer doesn't need to be present to use the code that's generated - it generates standard C#, using the code-first, fluent API - so the tool doesn't become a dependency to your project.
While giving you complete control over how the code is generated you'll be able to create, out of the box, sophisticated, consistent and **correct** Entity Framework code that can be regenerated when your model changes. And, since the code is written using partial classes, any additions you make to your generated code are retained across subsequent generations. The designer doesn't need to be present to use the code that's generated - it generates standard C#, using the code-first, fluent API - so the tool doesn't become a dependency to your project.

If you are used to the EF visual modeling that comes with Visual Studio, you'll be pretty much at home. The goal was to duplicate at least those features and, in addition, add all the little things that _should_ have been there. Things like:

Expand All @@ -20,9 +19,7 @@ If you are used to the EF visual modeling that comes with Visual Studio, you'll

and many other nice-to-have bits.

**Note:** This tool does not reverse engineer from the database (i.e., "database-first"). Microsoft has provided
tools for that, and there are other, well-maintained opensourced projects that provide that functionality as
well.
**Note:** This tool does not reverse engineer from the database (i.e., "database-first"). Microsoft has provided tools for that, and there are other, well-maintained opensourced projects that provide that functionality as well.

For comprehensive documentation, please visit [the project's documentation site](https://msawczyn.github.io/EFDesigner/).

Expand Down
Binary file modified src/DslPackage/Parsers/EF6Parser.exe
Binary file not shown.
Binary file modified src/DslPackage/Parsers/EFCore2Parser.exe
Binary file not shown.
Binary file modified src/DslPackage/Parsers/EFCore3Parser.exe
Binary file not shown.
Binary file modified src/DslPackage/Parsers/EFCore5Parser.exe
Binary file not shown.
15 changes: 14 additions & 1 deletion src/DslPackage/TextTemplates/EFCore5ModelGenerator.ttinclude
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,20 @@
Output("partial void OnModelCreatedImpl(ModelBuilder modelBuilder);");
NL();

Output("/// <inheritdoc />");
Output("/// <summary>");
Output("/// Override this method to further configure the model that was discovered by convention from the entity types");
Output("/// exposed in <see cref=\"T:Microsoft.EntityFrameworkCore.DbSet`1\" /> properties on your derived context. The resulting model may be cached");
Output("/// and re-used for subsequent instances of your derived context.");
Output("/// </summary>");
Output("/// <remarks>");
Output("/// If a model is explicitly set on the options for this context (via <see cref=\"M:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.UseModel(Microsoft.EntityFrameworkCore.Metadata.IModel)\" />)");
Output("/// then this method will not be run.");
Output("/// </remarks>");
Output("/// <param name=\"modelBuilder\">");
Output("/// The builder being used to construct the model for this context. Databases (and other extensions) typically");
Output("/// define extension methods on this object that allow you to configure aspects of the model that are specific");
Output("/// to a given database.");
Output("/// </param>");
Output("protected override void OnModelCreating(ModelBuilder modelBuilder)");
Output("{");
Output("base.OnModelCreating(modelBuilder);");
Expand Down
24 changes: 22 additions & 2 deletions src/DslPackage/TextTemplates/EFCoreModelGenerator.ttinclude
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,14 @@
NL();
}

Output("/// <inheritdoc />");
Output("/// <summary>");
Output("/// <para>");
Output("/// Initializes a new instance of the <see cref=\"T:Microsoft.EntityFrameworkCore.DbContext\" /> class using the specified options.");
Output("/// The <see cref=\"M:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)\" /> method will still be called to allow further");
Output("/// configuration of the options.");
Output("/// </para>");
Output("/// </summary>");
Output("/// <param name=\"options\">The options for this context.</param>");
Output($"public {modelRoot.EntityContainerName}(DbContextOptions<{modelRoot.EntityContainerName}> options) : base(options)");
Output("{");
Output("}");
Expand Down Expand Up @@ -449,7 +456,20 @@
Output("partial void OnModelCreatedImpl(ModelBuilder modelBuilder);");
NL();

Output("/// <inheritdoc />");
Output("/// <summary>");
Output("/// Override this method to further configure the model that was discovered by convention from the entity types");
Output("/// exposed in <see cref=\"T:Microsoft.EntityFrameworkCore.DbSet`1\" /> properties on your derived context. The resulting model may be cached");
Output("/// and re-used for subsequent instances of your derived context.");
Output("/// </summary>");
Output("/// <remarks>");
Output("/// If a model is explicitly set on the options for this context (via <see cref=\"M:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.UseModel(Microsoft.EntityFrameworkCore.Metadata.IModel)\" />)");
Output("/// then this method will not be run.");
Output("/// </remarks>");
Output("/// <param name=\"modelBuilder\">");
Output("/// The builder being used to construct the model for this context. Databases (and other extensions) typically");
Output("/// define extension methods on this object that allow you to configure aspects of the model that are specific");
Output("/// to a given database.");
Output("/// </param>");
Output("protected override void OnModelCreating(ModelBuilder modelBuilder)");
Output("{");
Output("base.OnModelCreating(modelBuilder);");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,20 @@ protected override void WriteOnModelCreate(List<string> segments, ModelClass[] c
Output("partial void OnModelCreatedImpl(ModelBuilder modelBuilder);");
NL();

Output("/// <inheritdoc />");
Output("/// <summary>");
Output("/// Override this method to further configure the model that was discovered by convention from the entity types");
Output("/// exposed in <see cref=\"T:Microsoft.EntityFrameworkCore.DbSet`1\" /> properties on your derived context. The resulting model may be cached");
Output("/// and re-used for subsequent instances of your derived context.");
Output("/// </summary>");
Output("/// <remarks>");
Output("/// If a model is explicitly set on the options for this context (via <see cref=\"M:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.UseModel(Microsoft.EntityFrameworkCore.Metadata.IModel)\" />)");
Output("/// then this method will not be run.");
Output("/// </remarks>");
Output("/// <param name=\"modelBuilder\">");
Output("/// The builder being used to construct the model for this context. Databases (and other extensions) typically");
Output("/// define extension methods on this object that allow you to configure aspects of the model that are specific");
Output("/// to a given database.");
Output("/// </param>");
Output("protected override void OnModelCreating(ModelBuilder modelBuilder)");
Output("{");
Output("base.OnModelCreating(modelBuilder);");
Expand Down
24 changes: 22 additions & 2 deletions src/DslPackage/TextTemplates/EditingOnly/EFCoreModelGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,14 @@ protected void WriteContextConstructors()
NL();
}

Output("/// <inheritdoc />");
Output("/// <summary>");
Output("/// <para>");
Output("/// Initializes a new instance of the <see cref=\"T:Microsoft.EntityFrameworkCore.DbContext\" /> class using the specified options.");
Output("/// The <see cref=\"M:Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder)\" /> method will still be called to allow further");
Output("/// configuration of the options.");
Output("/// </para>");
Output("/// </summary>");
Output("/// <param name=\"options\">The options for this context.</param>");
Output($"public {modelRoot.EntityContainerName}(DbContextOptions<{modelRoot.EntityContainerName}> options) : base(options)");
Output("{");
Output("}");
Expand Down Expand Up @@ -437,7 +444,20 @@ protected virtual void WriteOnModelCreate(List<string> segments, ModelClass[] cl
Output("partial void OnModelCreatedImpl(ModelBuilder modelBuilder);");
NL();

Output("/// <inheritdoc />");
Output("/// <summary>");
Output("/// Override this method to further configure the model that was discovered by convention from the entity types");
Output("/// exposed in <see cref=\"T:Microsoft.EntityFrameworkCore.DbSet`1\" /> properties on your derived context. The resulting model may be cached");
Output("/// and re-used for subsequent instances of your derived context.");
Output("/// </summary>");
Output("/// <remarks>");
Output("/// If a model is explicitly set on the options for this context (via <see cref=\"M:Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.UseModel(Microsoft.EntityFrameworkCore.Metadata.IModel)\" />)");
Output("/// then this method will not be run.");
Output("/// </remarks>");
Output("/// <param name=\"modelBuilder\">");
Output("/// The builder being used to construct the model for this context. Databases (and other extensions) typically");
Output("/// define extension methods on this object that allow you to configure aspects of the model that are specific");
Output("/// to a given database.");
Output("/// </param>");
Output("protected override void OnModelCreating(ModelBuilder modelBuilder)");
Output("{");
Output("base.OnModelCreating(modelBuilder);");
Expand Down
42 changes: 41 additions & 1 deletion src/Utilities/EF6Parser/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;

using log4net;
using log4net.Config;
Expand All @@ -19,6 +21,27 @@ internal class Program
public const int AMBIGUOUS_REQUEST = 6;
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

private static Assembly Context_Resolving(AssemblyLoadContext context, AssemblyName assemblyName)
{
// avoid loading *.resources dlls, because of: https://github.com/dotnet/coreclr/issues/8416
if (assemblyName.Name.EndsWith("resources"))
return null;

// try known directories
string found = context.Assemblies.Select(x => Path.Combine(Path.GetDirectoryName(x.Location), $"{assemblyName.Name}.dll")).Distinct().FirstOrDefault(File.Exists);

if (found != null)
return context.LoadFromAssemblyPath(found);

// try gac
found = Directory.GetFileSystemEntries(Environment.ExpandEnvironmentVariables("%windir%\\Microsoft.NET\\assembly"), $"{assemblyName.Name}.dll", SearchOption.AllDirectories).FirstOrDefault();

if (found != null)
return context.LoadFromAssemblyPath(found);

return null;
}

private static void Exit(int returnCode, Exception ex = null)
{
if (returnCode != 0)
Expand Down Expand Up @@ -90,7 +113,7 @@ private static int Main(string[] args)

log.Info($"Loading {inputPath}");
Environment.CurrentDirectory = Path.GetDirectoryName(inputPath);
Assembly assembly = Assembly.LoadFrom(inputPath);
Assembly assembly = TryLoadFrom(inputPath);
Parser parser = null;

try
Expand Down Expand Up @@ -143,5 +166,22 @@ private static int Main(string[] args)

return SUCCESS;
}

private static Assembly TryLoadFrom(string inputPath)
{
AssemblyLoadContext context = new AssemblyLoadContext("EFCore5Parser");
context.Resolving += Context_Resolving;

try
{
return context.LoadFromAssemblyPath(inputPath);
}
catch
{
string altPath = Path.ChangeExtension(inputPath, "dll");

return context.LoadFromAssemblyPath(altPath);
}
}
}
}
13 changes: 11 additions & 2 deletions src/Utilities/EFCore2Parser/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,19 @@ private static Assembly Context_Resolving(AssemblyLoadContext context, AssemblyN
if (library != null)
return context.LoadFromAssemblyName(new AssemblyName(library.Name));

// try known directories
string found = context.Assemblies.Select(x => Path.Combine(Path.GetDirectoryName(x.Location), $"{assemblyName.Name}.dll")).Distinct().FirstOrDefault(File.Exists);

if (found != null)
return context.LoadFromAssemblyPath(found);

// try gac
string[] foundDlls = Directory.GetFileSystemEntries(Environment.ExpandEnvironmentVariables("%windir%\\Microsoft.NET\\assembly"), $"{assemblyName.Name}.dll", SearchOption.AllDirectories);
found = Directory.GetFileSystemEntries(Environment.ExpandEnvironmentVariables("%windir%\\Microsoft.NET\\assembly"), $"{assemblyName.Name}.dll", SearchOption.AllDirectories).FirstOrDefault();

if (found != null)
return context.LoadFromAssemblyPath(found);

return foundDlls.Any() ? context.LoadFromAssemblyPath(foundDlls[0]) : null;
return null;
}

private static void Exit(int returnCode, Exception ex = null)
Expand Down
13 changes: 11 additions & 2 deletions src/Utilities/EFCore3Parser/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,19 @@ private static Assembly Context_Resolving(AssemblyLoadContext context, AssemblyN
if (library != null)
return context.LoadFromAssemblyName(new AssemblyName(library.Name));

// try known directories
string found = context.Assemblies.Select(x => Path.Combine(Path.GetDirectoryName(x.Location), $"{assemblyName.Name}.dll")).Distinct().FirstOrDefault(File.Exists);

if (found != null)
return context.LoadFromAssemblyPath(found);

// try gac
string[] foundDlls = Directory.GetFileSystemEntries(Environment.ExpandEnvironmentVariables("%windir%\\Microsoft.NET\\assembly"), $"{assemblyName.Name}.dll", SearchOption.AllDirectories);
found = Directory.GetFileSystemEntries(Environment.ExpandEnvironmentVariables("%windir%\\Microsoft.NET\\assembly"), $"{assemblyName.Name}.dll", SearchOption.AllDirectories).FirstOrDefault();

if (found != null)
return context.LoadFromAssemblyPath(found);

return foundDlls.Any() ? context.LoadFromAssemblyPath(foundDlls[0]) : null;
return null;
}

private static void Exit(int returnCode, Exception ex = null)
Expand Down
2 changes: 1 addition & 1 deletion src/Utilities/EFCore3Parser/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"EFCore3Parser": {
"commandName": "Project",
"commandLineArgs": "\"C:\\Users\\micha\\Downloads\\Dinaris.PsycheAdmin.EFDAL.dll\" c:\\temp\\parsertest.txt"
"commandLineArgs": "\"C:\\Code\\_Clients\\AWH\\SureImpactMVP\\Source\\SureImpact.Data\\bin\\Debug\\netcoreapp3.1\\SureImpact.Data.dll\" c:\\temp\\parsertest.txt"
}
}
}

0 comments on commit fd10351

Please sign in to comment.