cligenerator and DDL SQL

Posts   
 
    
MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 16-Jan-2015 23:17:23   

Can this be done? Do I need to look into the source to do this? Or do I have to stick to the designer menu option?

..\..\..\CliGenerator.exe Northwind.llblgenproj "" "SQL" "RDBMS" "Create DDL SQL" "SD.Presets.DDLSQL.CreateScript" ".\sql_test" 1 sql_test.txt

Same output below if I do "Update DDL SQL" as the template group with the UpdateScript preset.

Here's the output:


LLBLGen Pro Command line code generator v4.2.0.0.07082014
(c)2002-2014 Solutions Design. http://www.llblgen.com
Generates code for LLBLGen Pro projects on the command line.
Initializing...
Initialization complete.
Loading project 'Northwind.llblgenproj'
Project 'Northwind' loaded successfully from file 'Northwind.llblgenproj'.
Project validation successful.

=====================
Exception caught.
=====================
Message: No template bindings found for the specified language, platform and tar
get database. Aborting.
Source: CliGenerator
Stack trace:
   at SD.LLBLGen.Pro.Tools.CommandLineGenerator.Startup.StartProcess(String proj
ectFile, String rootNamespace, String languageName, String platformName, String
templateGroupName, String presetName, String destinationFolder, Boolean clearDes
tinationFolder, Boolean loadValuesFromProjectFile)

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 17-Jan-2015 08:08:10   

AFAIK, you can't do it right now. You may tweak the source code. Let me see if I can dig into it.

(Edit) The problem is the FrameworkName aprox at line Startup.cs:221 :

List<TemplateBindings> bindingsToUse = codeGenMetaData.LoadedTemplateBindingsManager
                                            .GetTemplateBindingsWithFilter(codeGenerationPreferences.LanguageName, 
                                                        codeGenerationPreferences.PlatformName, 
                                                        projectToGenerate.GetAllDriverIDsOfDatabasesWithMetaDataInProject().ToList(), 
                                                        codeGenerationPreferences.FrameworkName);

As you can see, the FrameworkName is taken from the project preferences, which could be "LLBLGen Runtime Framework", "Entity Framework v1", "NHibernate", etc. However the FrameworkName for DDL presets is ""DDL SQL". So the process actually found your "SD.Presets.DDLSQL.CreateScript" preset, your "Create DDL SQL" group, the "RDBMS" platform and "SQL" language, it tries to associate them with the actual target framework of your project (say "LLBLGen Runtime Framework", and that combination is not found in the bindings.

To fix that, you should write code to contemplate this situation. For instance:

...
// <@daelmo.fix>: fix to allo DDLSQL presets
if (presetToRun.Name.Contains("DDLSQL"))
{
    codeGenerationPreferences.FrameworkName = presetToRun.SupportedFrameworks.First();
}
// </@daelmo.fix>
                
List<TemplateBindings> bindingsToUse = codeGenMetaData.LoadedTemplateBindingsManager
                                            .GetTemplateBindingsWithFilter(codeGenerationPreferences.LanguageName, 
                                                        codeGenerationPreferences.PlatformName, 
                                                        projectToGenerate.GetAllDriverIDsOfDatabasesWithMetaDataInProject().ToList(), 
                                                        codeGenerationPreferences.FrameworkName);
... 

Actually, above code fix this situation. Try it, remplace the actual cligenerator.exe an run your batch like:

cligenerator ...\NW.llblgenproj NW.LLBL.Tests SQL RDBMS "Create DDL SQL" SD.Presets.DDLSQL.CreateScript ...\_SQLScripts 1 genoutput.log

Finally, I think this case was never was tested because the cligenerator.exe tool is meant to generate code, whatever if your target framework (LLBLG, EF, NH, etc). DDL generation is actually part of the process to sync your model with your db and it was introduced with model-first approach. As a matter of fact, the cligenerator tool generates your DDL scripts if it has to, based on the project validation. So if you want this because you made changes, the built-in process do that already. If you want this, just to generate on-demand sql, then use the fix above.

Hope that helps wink

David Elizondo | LLBLGen Support Team
MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 21-Jan-2015 19:39:02   

Thanks daelmo, sorry for not getting back sooner. Just thought I'd add some additional comments on how I got this to work in case someone else tries to do this edge scenario.

I created some FluentMigrator templates (instead of SQL DDL, which I can share if others are interested, which handle Up/Down/Create/Update scenarios), and I'm able to use them inside the designer without modifying any core templates, just by adding a few files to the appropriate folders inside of program files (relative paths inside the project file configuration settings don't seem to work for these templates, seems like for the DDL operations in the designer, the template/task/preset files need to be in the respective program files folder). Any way, that works nicely.

The cligeneration works now by making changes to the cligenerator code (I cloned and renamed the cloned project and exe to keep my stuff separate and not overwrite the default generator). In order for it to work, I actually pass the binding names into the cligenerator.exe function in the command line as additional parameters. I changed the source to allow that and to assume that additional parameters (beyond the possible 9 parameters out-of-the-box) are binding names.

Then inside of StartProcess, I do this:


List<TemplateBindings> bindingsToUse;
if (bindingNamesToUse == null || bindingNamesToUse.Length == 0)
{
    bindingsToUse = codeGenMetaData.LoadedTemplateBindingsManager
        .GetTemplateBindingsWithFilter(codeGenerationPreferences.LanguageName,
        codeGenerationPreferences.PlatformName,
        projectToGenerate.GetAllDriverIDsOfDatabasesWithMetaDataInProject().ToList(),
        codeGenerationPreferences.FrameworkName);
}
else
{
    bindingsToUse = codeGenMetaData.LoadedTemplateBindingsManager
        .KnownTemplateBindings.Where(k => bindingNamesToUse.Any(bn => bn.Equals(k.Key, StringComparison.OrdinalIgnoreCase)))
        .Select(k => k.Value)
        .ToList();
}

Pretty flexible, and I think this might work well for other things as well in the future.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 22-Jan-2015 04:15:13   

Thanks for the feedback.

Posts: 1
Joined: 30-Jun-2017
# Posted on: 01-Jul-2017 15:36:06   

I'm very interested to see your Fluentmigrator code generation bindings, as I was planning to write some myself. I've never used LLBLGENPRO but I am looking for a round trip engineering tool and think it could be a good fit.