ConfigFileHelper.ReadConnectionString locations

Posts   
 
    
WilliamB
User
Posts: 17
Joined: 10-Feb-2022
# Posted on: 25-Feb-2022 19:52:16   

Quick super basic question here:

From which location(s) does this method tries to read connections strings?

WilliamB
User
Posts: 17
Joined: 10-Feb-2022
# Posted on: 25-Feb-2022 20:10:42   

I realized a little bit late that I need to provide more context. For that I apologize.

We have in a project a LTP template that goes like this:

const string ConnectionKeyString = "Main.ConnectionString";
OracleConnection conn = new OracleConnection(SD.LLBLGen.Pro.ORMSupportClasses.ConfigFileHelper.ReadConnectionStringFromConfig(ConnectionKeyString));

By debugging we can see that ConfigHelper.ReadConnectionString is returning an empty string, so the 2nd line fails.

  • What would be the path where the ConfigHelper would try to load a configuration file?
  • What should be the name of the file?
  • What format should be used? Can we get example?

Thanks in advance.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 27-Feb-2022 10:20:10   

the config file is the config file of the application, which is a netfx term, so app/web.config. If you're on .netcore/.net5+ then you need to use the RuntimeConfiguration system, which is specifying the connection string in code. https://www.llblgen.com/Documentation/5.9/LLBLGen%20Pro%20RTF/Using%20the%20generated%20code/gencode_runtimeconfiguration.htm

Frans Bouma | Lead developer LLBLGen Pro
WilliamB
User
Posts: 17
Joined: 10-Feb-2022
# Posted on: 28-Feb-2022 15:36:05   

Thanks Otis,

The error I am getting is not launched while using the generated code, but while generating the code.

Here is the task defined:

<task name="uFACTS.Tasks.Common.Utility.General.MsgDefClassGenerator" assemblyFilename="SD.LLBLGen.Pro.TaskPerformers.dll" 
            taskPerformerClass="SD.LLBLGen.Pro.TaskPerformers.CodeEmitter" description="Generates the MsgDef static classes" isOptional="true">
            <supportedPlatforms/>
            <supportedTemplateGroups/>
            <dependencies/>
            <parameters>
                <parameter name="destinationFolder" defaultValue="" isOptional="false" description="The folder to generate the code in"/>
                <parameter name="filenameFormat" defaultValue="MsgDefType.[extension]" isOptional="false" description="The destination file format specification"/>
                <parameter name="templateID" defaultValue="uFACTS_MsgDefTypeTemplate" isOptional="false" description="The ID of the template to use." valueType="templateID"/>
                <parameter name="emitType" defaultValue="generic" isOptional="false" description="The type of code generation to perform." valueType="emitType"/>
                <parameter name="templateBindingDefinitionName" defaultValue="" isOptional="true" description="The name of the TemplateBindings from which to pick the templateID specified. Specifying this parameter will always force the templateID to be picked from the templateBindings with the name specified."/>
                <parameter name="failWhenExistent" defaultValue="false" isOptional="true" description="Flag to signal what to do when the destination file already exists." valueType="boolean"/>
            </parameters>
        </task>`

...and here are the content of the templates

MsgDefTypeTemplate

namespace uFACTS.Utility.General
{
<# uFACTS_MsgDefType_GetTypes #>
}

MsgDefType_GetTypes

<[ System.Diagnostics ]>

<% 
        //Debugger.Break();
        Hashtable groups = new Hashtable();
        const string ConnectionKeyString = "Main.ConnectionString";
        OracleConnection conn = new OracleConnection(SD.LLBLGen.Pro.ORMSupportClasses.ConfigFileHelper.ReadConnectionStringFromConfig(ConnectionKeyString));
        conn.Open();
        
        OracleCommand cmd = new OracleCommand("select msg_def_nu, const_na, msg_desc, msg_text from ui_msg_def order by msg_def_nu", conn);
        OracleDataReader reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            string group = string.Empty;
            string name = reader["const_na"].ToString();
            if (!name.Contains("."))
            {
                group = "General";
            }
            else
            {
                group = name.Substring(0, name.IndexOf("."));
                name = name.Substring(name.IndexOf(".") + 1);
            }
            
            if (!groups.Contains(group))
            {
                groups.Add(group, new List<string>());
            }
            
            string tmp = "\t\tpublic const int " + name + " = " + reader["msg_def_nu"].ToString() + ";";
            tmp = tmp.PadRight(50, ' ');
            tmp += "// " + reader["msg_desc"].ToString().Replace("\r\n", "\n").Replace("\n", " ") + " - \"" + reader["msg_text"].ToString().Replace("\r\n", "\n").Replace("\n", " ") + "\"\r\n";
            ((List<string>)groups[group]).Add(tmp);
        }
        reader.Close();
        conn.Close();
        
        foreach (DictionaryEntry de in groups)
        {
            string output = string.Empty;
            output += "\tpublic static partial class MD"+de.Key.ToString()+"\r\n";
            output += "\t{\r\n";
            ((List<string>)de.Value).Sort();
            foreach (string val in (List<string>)de.Value)
            {
                output += val;
            }
            output += "\t}\r\n\r\n";
            __outputWriter.Write(output);
        }
%>

The problem being the connection string is empty string when conn.Open() is called.

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 28-Feb-2022 23:18:21   

Please provide the error you are getting?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 01-Mar-2022 10:10:04   

You're trying to execute code meant for runtime during template generation. That's not how this works. Connection strings are obtained from the project. See this app.config template from the EF 6 template set:

<%
    Project currentProject = _executingGenerator.ProjectDefinition;
%><?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionStrings>
        <!-- please adjust the connection string embedded in the element below to target the proper catalog / server using the proper user / password combination -->
        <add name="<%=currentProject.CreateConnectionStringKeyNameForDatabase(_executingGenerator.DriverID)%>" connectionString="metadata=res://*/<%=_executingGenerator.ActiveSourceElementsContainerName%>.csdl|res://*/<%=_executingGenerator.ActiveSourceElementsContainerName%>.ssdl|res://*/<%=_executingGenerator.ActiveSourceElementsContainerName%>.msl;provider=<%=SD_EF_GeneralUtils.DriverIdToProviderName(_executingGenerator.DriverID)%>;provider connection string=&quot;<%=currentProject.CreateConnectionStringForDatabase(_executingGenerator.DriverID)%>&quot;" providerName="System.Data.EntityClient" />
    </connectionStrings>
</configuration> 

Please also don't use __outputwriter in your template. Use <%=variable%>

Frans Bouma | Lead developer LLBLGen Pro
WilliamB
User
Posts: 17
Joined: 10-Feb-2022
# Posted on: 01-Mar-2022 14:12:28   

Thank you. for your answers and suggestions. The error was "Invalid connection string" since the connection string is an empty string once reaches the line that should open the Connection.

Thank you Otis. Your answer was very clarifying.