Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF and EF - How to force host to use its own connection string

Please excuse this question from an extreme newbie. I couldn't find the answer anywhere else.

I am writing a solution using Entity Framework and WCF. I will be writing several different clients. I have placed the database connection string in both the Entity Framework project's app.config and the WCF host's app.config file.

In the host class, I wrote a simple test service contract with one method that simply retrieves all the customers from the database (from EF), called GetAllCustomers(). I then wrote a simple console client app to call GetAllCustomers() of the host and write all the customers' first and last names to the console.

When I tried running the client, I got an error that says, "No connection string named 'TRS11Entities' could be found in the application config file.

If I copy the connection string to the client console app's app.config file, it works fine, but if I comment it out, it doesn't work again.

Since the WCF host is doing the talking to the database, not the client directly, I don't understand why the client would need a connection string. I can only guess that the connection string is being passed up the chain from the client to the WCF host to Entity Framework. How can I make the WCF host tell .NET, "The buck stops here! Use my app.config's connection string and stop bothering the client for this info!"

If it matters, I'm using Visual Studio Pro 2012, with all projects written in C# and targeting the V4.5 .NET framework.

From APP.CONFIG in the WCF service project:

  <system.serviceModel>
    <services>
      <service name="OrsonServiceLibrary.Service1">
        <endpoint address="localhost" binding="basicHttpBinding" name="TRS11Entities"
          contract="OrsonServiceLibrary.IService1">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/Design_Time_Addresses/OrsonServiceLibrary/Service1/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, 
          set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <connectionStrings>
    <add name="TRS11Entities" connectionString="metadata=res://*/TRS11Model.csdl|res://*/TRS11Model.ssdl|res://*/TRS11Model.msl;provider=FirebirdSql.Data.FirebirdClient;provider connection string='character set=NONE;data source=localhost;initial catalog=&quot;C:\Program Files (x86)\TRS11\Data\DATA1100.FDB&quot;;user id=sysdba;password=masterkey'" providerName="System.Data.EntityClient" />
  </connectionStrings>

From APP.CONFIG in the Entity Framework project:

  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="TRS11Entities" connectionString="metadata=res://*/TRS11Model.csdl|res://*/TRS11Model.ssdl|res://*/TRS11Model.msl;provider=FirebirdSql.Data.FirebirdClient;provider connection string='initial catalog=&quot;C:\Program Files (x86)\TRS11\Data\DATA1100.FDB&quot;;user id=sysdba;password=masterkey;data source=localhost'" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>

From APP.CONFIG in the console client app:

  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:8000/Service1" contract="OrsonServiceLibrary.IService1" binding="basicHttpBinding" />
    </client>
  </system.serviceModel>

  <!--<connectionStrings>
    <add name="TRS11Entities" connectionString="metadata=res://*/TRS11Model.csdl|res://*/TRS11Model.ssdl|res://*/TRS11Model.msl;provider=FirebirdSql.Data.FirebirdClient;provider connection string='character set=NONE;data source=localhost;initial catalog=&quot;C:\Program Files (x86)\TRS11\Data\DATA1100.FDB&quot;;user id=sysdba;password=masterkey'" providerName="System.Data.EntityClient" />
  </connectionStrings>-->

Code for GetAllCustomers() function in the WCF Service project:

public HashSet<CUSTOMER> GetAllCustomers()
{
    var db = new TRS11Entities();

    HashSet<CUSTOMER> TheCusts = new HashSet<CUSTOMER>();

    foreach (CUSTOMER c in db.CUSTOMERs)
    {
        TheCusts.Add(c);
    }

    return TheCusts;
}

Console client app code:

static void Main(string[] args)
{
    Console.WriteLine("Press Enter to begin.");
    Console.ReadLine();

    Service1 MyService = new Service1();

    HashSet<CUSTOMER> cl = MyService.GetAllCustomers();

    foreach (CUSTOMER c in cl)
    {
        Console.WriteLine(c.CUSTFNAME + " " + c.CUSTLNAME);
    }

    Console.WriteLine("Press Enter to exit.");
    Console.ReadLine();
}

Host application code:

class Program
{
    static void Main(string[] args)
    {
        ServiceHost hostA = null;

        try
        {
            hostA = new ServiceHost(typeof(Service1));
            hostA.Open();

            Console.WriteLine();
            Console.WriteLine("Host started.  Press Enter to terminate host.");
            Console.ReadLine();

        }
        finally
        {
            if (hostA.State == CommunicationState.Faulted)
                hostA.Abort();
            else
                hostA.Close();
        }
    }
}

Thanks, Joe

like image 546
JoeMjr2 Avatar asked Oct 21 '22 21:10

JoeMjr2


2 Answers

Something tells me, that you're actually creating an instance of the service in your client app instead of using a proxy/channel.

What is the Service1 type in the client app code? Is it OrsonServiceLibrary.Service1 ?

Service1 MyService = new Service1();

If so, just remove reference to the service project and Add Service Reference instead. This will generate a proxy, which you can use for accessing your service.

like image 147
Alex Pokislyuk Avatar answered Oct 28 '22 20:10

Alex Pokislyuk


The client app isn't passing the connection to your wcf service. My guess is that you are making an un-intentional call to your database in your client app. That would explain the error and why it works when you add the connection string to your console app.

Hope that helps. Post some code and we may be able to help more.

like image 37
Ben Tidman Avatar answered Oct 28 '22 21:10

Ben Tidman