none
teradata dll, which is used at runtime, the dll or the td client installed on the server RRS feed

  • Question

  • Hi,

           I am reading Teradata with c# and using Teradata.Client.Provider.dll as a Reference in my build.   That dll has a version number, 15.0.0.1 .  I set Specific Version to True.  The Teradata client on the server that my console program runs on is a slightly different version, 15.11.0.0 .   So which version gets used at runtime to access our big Teradata DB in the sky, the dll version or the td client installed on the server?  Also, Referencing the dll file doesn't build a completely stand alone binary that can access Teradata from anywhere, right?  I still need a Teradata client installed on the server I run my console app on to access the Teradata DB, right?

    Tuesday, July 3, 2018 12:42 PM

Answers

  • The CLR algorithm is documented here. The CLR calculates the version by looking at what you referenced and then applies any binding redirects. Once it has identified the version it looks in the GAC if the assembly is strongly named. The version must be in the GAC. If it isn't found then it looks in the search path which is generally the app directory but could be set to something else before the domain gets loaded. If it finds the assembly with the same version it loads it otherwise it fails.

    If your provider assembly is strongly named then you must have the 15.0.0.1 assembly either in the GAC or local path. It is unclear what you mean by client on the server. There is only 1 running app per process and its references are the one's being used. Any remote connections are completely irrelevant as they are different processes. It is possible for a "remote" client to be using one version of some assembly and the "server" to be using another. Happens all the time. But a single process won't have multiple versions of the same assembly loaded. The first load wins.

    If your server needs access to an assembly then it must be on the server with your server code (or in the GAC). If you need to reference a newer version of an assembly without recompiling your code then you'll need to use a binding redirect.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by etlman Tuesday, July 3, 2018 3:24 PM
    Tuesday, July 3, 2018 1:49 PM
    Moderator

All replies

  • The CLR algorithm is documented here. The CLR calculates the version by looking at what you referenced and then applies any binding redirects. Once it has identified the version it looks in the GAC if the assembly is strongly named. The version must be in the GAC. If it isn't found then it looks in the search path which is generally the app directory but could be set to something else before the domain gets loaded. If it finds the assembly with the same version it loads it otherwise it fails.

    If your provider assembly is strongly named then you must have the 15.0.0.1 assembly either in the GAC or local path. It is unclear what you mean by client on the server. There is only 1 running app per process and its references are the one's being used. Any remote connections are completely irrelevant as they are different processes. It is possible for a "remote" client to be using one version of some assembly and the "server" to be using another. Happens all the time. But a single process won't have multiple versions of the same assembly loaded. The first load wins.

    If your server needs access to an assembly then it must be on the server with your server code (or in the GAC). If you need to reference a newer version of an assembly without recompiling your code then you'll need to use a binding redirect.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by etlman Tuesday, July 3, 2018 3:24 PM
    Tuesday, July 3, 2018 1:49 PM
    Moderator
  • Michael,

          Thanks.  This is what I mean by Teradata client on the server.  I did a little experiment.   I deleted a working Teradata.Client.Provider.dll from my Visual Studio build, and put a slightly different version td .dll file in the build. It was 15.0.0.0 to 15.11.0.0 .   Then I transported the binary to the server and ran it.   Boom it blows up immediately (see below) on a file not found for a lousy .11 difference in version numbers.  Teradata is incredibly fussy about version numbers, I never have this problem with Oracle OLEDB.  With Oracle I don't even know what the version numbers of the database and client installs are.   This is absolutely killing us with SSIS.   At least with Visual Studio/c# I feel I have a little control with being able to add a particular version .dll file in the build and setting Specific Version to True.  (we developers have little control over the Teradata Client installed on the servers that our console applications run on in this big company.)   

    Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Teradata.Client.Provide
    r, Version=15.11.0.0, Culture=neutral, PublicKeyToken=76b4xyz12e04956c' or one of its dependencies. The system
     cannot find the file specified.
       at teradataDetractor.writeOutputFile.writeSelectedOutput(String extractNumber, String sqlName)
       at teradataDetractor.Program.Main(String[] args)



    • Edited by etlman Tuesday, July 3, 2018 2:41 PM
    Tuesday, July 3, 2018 2:15 PM
  • For strongly named assemblies the version number must exactly match. That is the whole purpose of strong naming and is designed to ensure you never run against an assembly you didn't test against. 

    As for how to solve it that depends on what your client is. You mentioned SSIS so if this is a client hosted in another process then you're stuck with whatever the host app loads. There is nothing you can do about it but since the assembly is already loaded you wouldn't get any errors. If the app itself needs to target a newer version then it would need to use a binding redirect. But SSIS requires things to be loaded from the GAC so provided the correct version of that DLL is in the GAC then you should be fine.

    Did you install the version in the GAC? The error you're posting could be a versioning issue but it sounds like it isn't finding the assembly at all. It needs to be in the GAC to get loaded AFAIK. We have custom SSIS tasks ourselves and everything we ship or rely on has to be there. So simply installing to the GAC may solve your problem.

    But looking at the call stack this looks like a normal console app. In that case just add a binding redirect to your config file and it can use the newer version. Publishers generally create a machine-level binding redirect for hotfixes but for individual apps you are responsible for doing this yourself.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, July 3, 2018 3:13 PM
    Moderator
  • Ok, this is exciting.  I tried the "binding redirect" that Michael suggested and it worked.  I didn't even have to recompile the program, I just used binaries that I had and changed the .config file.   Here are instructions for its use and the example that worked for me is shown below.   It goes in your myprog.exe.config file inside of <Configuration> but not inside <AppSettings> or <ConnectionStrings>.   I would argue you only put this in the myprog.exe.config that is on the server, not in the app.config for your visual studio build.   You get the assemblyIdentity and publicKeyToken from the error message you get when you run it without the binding redirect.  Don't copy this solution verbatim, I changed the token information to keep our environment private.  The "old Version" is the version of the dll file you compiled with.  The new version is the version of the Teradata client you have installed on your run server.  My case is funny, but in my case the newVersion was older than my oldVersion.   So now you have complete control to run on whatever Teradata Client you have installed on your run server.  Thanks Michael.       .... Flash   

     <runtime> 
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
             <dependentAssembly> 
                <assemblyIdentity name="Teradata.Client.Provider" 
                                  publicKeyToken="76b4225kke2e04956c" 
                                  culture="neutral" /> 
                <bindingRedirect oldVersion="15.11.0.0" 
                                 newVersion="15.0.0.0"/> 
             </dependentAssembly> 
          </assemblyBinding> 
       </runtime> 





    • Edited by etlman Tuesday, July 3, 2018 6:11 PM
    Tuesday, July 3, 2018 3:35 PM
  • Michael,  I was wondering if you would speculate on another oddity we discovered.  My laptop where I build my ssis packages has Teradata 15.11.00.00 .  I am using Visual Studio 2013, and I think it's SSIS 2014 to create my SSIS packages.  An Azure expert told us to manually edit the .dtsx Package file and put 14.11.0.0 as the version number for the Teradata client, regardless of the version that was there.   This works on an Azure partition with Attunity (I don't think that matters) and a Teradata Client that shows as 15.11.01.01 in Azure Portal Utilities.   It also works on the development server I have been describing for the c# work above, which is Teradata client version 15.0.0.0.   Do you have any idea why referencing a Teradata version that doesn't even appear to be installed on the machine works? 
      If you don't manually edit the .dtsx file you get a "Could not create a managed connection manager."  message.
    • Edited by etlman Thursday, July 5, 2018 2:58 PM
    Thursday, July 5, 2018 2:19 PM
  • It depends on where you made that change in the DTSX file. My gut instinct is that it is simply changing the version of the designer that is loaded. It is also possible that the engineer was having you target the older version (for VS 2013) but there is a binding redirect to bring it up to 15.11 at runtime. Could be a problem running the newer version on the older version of VS. 

    The best bet would probably be to ask the engineer who told you that. I assume they were helping you work around another issue you had and this would resolve it for you.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, July 5, 2018 2:27 PM
    Moderator
  • Michael,   I did ask him but he's the strong silent type.   If I get him face to face he may tell me.   You can do redirects with all this ssis infrastructure stuff?   I mean you are doing redirects for the dtexec executable or something? 
    • Edited by etlman Thursday, July 5, 2018 3:31 PM
    Thursday, July 5, 2018 3:20 PM
  • Not directly because you don't own the SSIS executables but again all the runtime stuff comes from the GAC. A publisher can put a binding redirect into the GAC so when your app requests v1 then it can silently give you back v2 anyway. This is mainly designed for security/critical hotfixes that need to be patched without changing the apps that run on them. Technically I guess you could also do it via machine.config. Since the engineer didn't discuss how or why it works I'd just be guessing at this point though.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, July 5, 2018 3:44 PM
    Moderator
  • Michael,   When I looked at the GAC on our Development server the situation for ssis became clear.  The development server, in the GAC, had Policies redirecting from teradata 11.x to teradata 14.11.0.0 to the 15.0.0.0 we knew was on the server . It stopped at 14.11, there wasn't even the 15.0 version that was installed on the server.  So now I see how it works.   SSIS puts in the version of teradata you install on your development laptop and there better be a GAC policy that corresponds to that when you try to run your Package on the server.   If you manually edit your Package you can force it to a Policy that exists on your server, which is the equivalent of a binding redirect for c# (although much more primitive).   Thanks for all your help with this, this teradata development laptop/server mismatch has been a thorn in our sides for years.   Without knowing about the GAC and binding redirects it was a hard situation to understand.   This is a big organization.   A completely different group of people decide what version of teradata should be on the laptops (and sometimes they push new versions without asking) than the people who work with the servers (mostly application development people).
    • Edited by etlman Tuesday, July 17, 2018 5:15 PM
    Tuesday, July 17, 2018 5:11 PM
  • Glad to hear you've figured it out. Just one correction though - 

    "SSIS puts in the version of teradata you install on your development laptop"

    SSIS doesn't install anything to the GAC except when it installs itself during setup.  Installing to the GAC requires admin privileges and SSIS doesn't have that (in a typical situation) Redirect policies are put there (generally) by the publisher and this is generally only done for hotfixes. My guess is that somebody ran gacutil against the v15 version of Teradata and that added it to the GAC along with the redirect policy. But that would just be a guess.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, July 17, 2018 5:59 PM
    Moderator
  • Michael,

          Just to clarify when I said "puts in" I meant put in the Package.dtsx file.   For those of you following, if you have a teradata connection you will have a line like this in your Package.dtsx file:

    CreationName="ADO.Net:Teradata.Client.Provider...., Teradata.Client.Provider, Version=14.11.0.0,  ....

    If you manually edit the Version in the package.dtsx you can redirect the server execution of your package to a teradata version that is pointed to by an existing GAC Policy redirect on the server.  A kludgey fix I know and one you can't implement by using the ssis gui, but it works if you have the laptop/server teradata mismatch like we do. 

    Tuesday, July 17, 2018 6:34 PM