locked
Entity Framework Connection failing RRS feed

  • Question

  •  

    This must be a simple thing but I can't seem to get the context to connect once I've generated a new model. The model is created and compiled. I created the model in a Classlibrary project and it added an app.config connection string.

     

    I then use a Web app to access the model. I've added the same connection string into web.config but it continues to fail.

     

    I'm not sure what to make of the connection string and its reference to the 3 schema files that don't exist even after compilation/generation. The error is:

     

    The specified metadata path is not valid. A valid path must be either an existing directory, an existing file with extension '.csdl', '.ssdl', or '.msl', or a URI that identifies an embedded resource.

     

    I tried this both through the business object (seperate project) and by directly adding the model to the Web project. In both situations it compiles and I see the objects properly but the connection fails.

     

    Any idea what's missing?

     

    TimeTrakkerEntities.TimeTrakkerContext context = new TimeTrakkerEntities.TimeTrakkerContext();
     
     var result = from c in context.tt_customers
                  where c.Company.CompareTo("G") < 0
                  select c;
     
     foreach(tt_customers cust  in result)
     {
         Response.Write(cust.Company + "<br>");
     }
     
    Also tried:
     
    TimeTrakkerEntities.TimeTrakkerContext context = new TimeTrakkerEntities.TimeTrakkerContext("TimeTrakkerModel");
     
    where the that's the key for the connection string in web.config.
     
     
     
    Thursday, August 30, 2007 7:43 AM

Answers

  • The three main project systems that we support each have their own way of telling the runtime where to find the C/M/S files that are generated during build.

     

    Windows Applications

    * metadata=.\Model.csdl|.\Model.ssdl|.\Model.msl;provider=...

     

    The '.' here is a reference to the current working directory when the Windows application is executed.  This doesn't work as well for class libraries, since they are going to be loaded by some other process.

     

    Web Applications

    * metadata=~/bin/Model.csdl|~/bin/Model.ssdl|~/bin/Model.msl;provider=...

     

    The '~' here is interpreted by the runtime as the root of the virtual directory for the web application.  If you change the directory structure of the application when you deploy it, you will need to adjust this path as well.  In a web application, the runtime can't use absolute paths (and there is no current working directory), so it has to use a path relative to the virtual directory root.

     

    Web Sites

    * metadata=res://*;provider=...

     

    The web site project system builds code on the fly using Build Providers, and places these assemblies in temp folders deep in the .Net directory structure.  There is no way to reliably deploy files that, you could argue, are really code (the C/M/S files) but don't actually compile into assemblies.  So, for Web Sites, the C/M/S files are embedded as resources into the assembly.  If you look at a web site project, the EDMX item template will add a reference to a new build provider for all EDMX files (this build provider splits the file into its three parts and then embeds them).

     

    Because we don't know the name of the assembly that ASP.NET will build, the '*' in there tells the runtime to search through all embedded resources in all loaded modules looking for C/M/S resources.

     

    One thing we have on our list is to add an MSBuild task (and get rid of EdmxDeploy.exe) so that you could also embed the C/M/S files as resources in a Windows or Web Application.  It looks like, from your post Julie, that we should consider adding some additional nobs to this MSBuild task, giving you some control over the target directory.

    Thursday, August 30, 2007 5:39 PM

All replies

  • Rick,

     

    Please post:

    1. the portion of your web.config that contains the entity connection string

    2. the folder structure of your web app

     

    Thanks,

    Zlatko

    Thursday, August 30, 2007 4:11 PM
  •  

    Rick,

     

    While you edit the EDMX file (either in the designer or the raw code) it outputs csdl, ssdl and msl file into the debug folder.

     

    Those are in your class library project.

     

    The connection string has a reference to those files and a relative path. That's the metadata attribute.

     

    So in the connection string in the web.config, you need to point directly to them.

     

    I am trying to see how you can tell the code generator where to place the output files. But in the meantime, I moved them into c:\efmodels\ so that I can share the dll and anythig that uses them.

     

    By defaul the connection strin glooks like this:

        <add name="Entities" connectionString="metadata=.\Model.csdl|.\Model.ssdl|.\Model.msl;provider=System.Data.SqlClient;provider connection string='Data Source=.\SQLEXPRESS;AttachDbFilename=&quot;C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\AdventureWorksLT_Data.mdf&quot;;Integrated Security=True;Connect Timeout=30;User Instance=True'" providerName="System.Data.EntityClient" />

    in the web site that references the dll, the connection string looks like this:

     

    <add name="Entities"
         connectionString="metadata=c:/efmodels/aw/Model.csdl|c:/efmodels/aw/Model.ssdl|c:/efmodels/aw/Model.msl;
         provider=System.Data.SqlClient;
         provider connection string='Data Source=.\SQLEXPRESS;AttachDbFilename=&quot;C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\AdventureWorksLT_Data.mdf&quot;;Integrated Security=True;Connect Timeout=30;User Instance=True'"
         providerName="System.Data.EntityClient" />

     

    So now I just need to be sure that whenever I modify the EDMX and it regens those files, it puts them into c:\efmodels\aw. I don't want ALL of the compiler output to go there. Hopefully this won't require an MSBuild task. It is much too common of a scenario.

     

    In fact, rather than spending all day trying to figure that out, I'll start a new thread!

    Thursday, August 30, 2007 5:04 PM
  • The three main project systems that we support each have their own way of telling the runtime where to find the C/M/S files that are generated during build.

     

    Windows Applications

    * metadata=.\Model.csdl|.\Model.ssdl|.\Model.msl;provider=...

     

    The '.' here is a reference to the current working directory when the Windows application is executed.  This doesn't work as well for class libraries, since they are going to be loaded by some other process.

     

    Web Applications

    * metadata=~/bin/Model.csdl|~/bin/Model.ssdl|~/bin/Model.msl;provider=...

     

    The '~' here is interpreted by the runtime as the root of the virtual directory for the web application.  If you change the directory structure of the application when you deploy it, you will need to adjust this path as well.  In a web application, the runtime can't use absolute paths (and there is no current working directory), so it has to use a path relative to the virtual directory root.

     

    Web Sites

    * metadata=res://*;provider=...

     

    The web site project system builds code on the fly using Build Providers, and places these assemblies in temp folders deep in the .Net directory structure.  There is no way to reliably deploy files that, you could argue, are really code (the C/M/S files) but don't actually compile into assemblies.  So, for Web Sites, the C/M/S files are embedded as resources into the assembly.  If you look at a web site project, the EDMX item template will add a reference to a new build provider for all EDMX files (this build provider splits the file into its three parts and then embeds them).

     

    Because we don't know the name of the assembly that ASP.NET will build, the '*' in there tells the runtime to search through all embedded resources in all loaded modules looking for C/M/S resources.

     

    One thing we have on our list is to add an MSBuild task (and get rid of EdmxDeploy.exe) so that you could also embed the C/M/S files as resources in a Windows or Web Application.  It looks like, from your post Julie, that we should consider adding some additional nobs to this MSBuild task, giving you some control over the target directory.

    Thursday, August 30, 2007 5:39 PM
  • I guess I got distracted and didn't start a new thread.

     

    You make a great case for not creating EDMs inside of a website project!  I hate not knowing where my stuff is.

     

    A class project creates the CSDL the winforms way.

     

    In a single developer solution (on one machine), it makes sense to just say that for the purposes of development, modify the config of the client project that is using the dll, pointing the metadata to whatever path the dll builds the files into. When it comes to deployment, you can put the schema files whereever you want and modify the metadata attribute in the config accordingly.

     

    In a multi-developer environment, being able to define the target directory gets more critical. Especially if the model is getting adjusted while other developers are coding against it.

     

    Is there a workaround to do this currently? Even if it's not pretty?

     

    And yes please ... add those nobs!

    Thursday, August 30, 2007 6:10 PM
  • Julie,

     

    You can use the |DataDirectory| macro. By default it's set by ASP.NET to the App_Data subfolder of your web app but you can override it in your .asax to point anywhere else, e.g.:

     

    Code Snippet
    AppDomain.CurrentDomain.SetData(@”|DataDirectory|”, your_local_path);

     

     

     

     

    Zlatko Michailov

    Program Manager, Data Programmability

    Microsoft Corp.

     

    Thursday, August 30, 2007 6:28 PM
  • If you look in the .csproj file, the item template added a build step that calls EdmxDeploy.exe.

     

    EdmxDeploy.exe -?
    Usage: EdmxDeploy input_path output_path

     

    These are set to default to your project directory and the VS output directory, but you could change these to point to where ever you want.  EdmxDeploy reads all EDMX files, in all directories starting at 'input_path' and then writes out the C/M/S files to the 'output_path' (recreating any directory structures).

     

    EdmxDeploy.exe is only used for Windows and Web Applications and will be replaced by an MSBuild task in later releases.  Web Sites use the build provider.

    Thursday, August 30, 2007 6:35 PM
  •  

    Thanks everybody...

     

    I got it running by using virtual path syntax for the path pointers.

     

    I guess I'm confused why these files are even required at runtime. Shouldn't this stuff be self contained and external? Why this requirement for external files, three of them no less? Seems like the default should be to embed them into the assembly that compiled the model with an *option* to store the files externally.

     

    I suspect the idea is that you can make some adjustments to the model without recompilation? How important is this really?

     

    So, based on what you said here right now there's nothing that can automatically move the generated model files from a class project to the 'deployed' location short of creating my own build task (or leaving the model alone after copying).

     

     

     

     

     

    Thursday, August 30, 2007 11:44 PM
  •  

    Rick

    since this hasn't been replied to yet, I just wanted to point out that having the files separate allows loose coupling.

     

    for example you can have your csdl defined, then a storage model and a mapping between the two.

     

    What if you wanted to point to a different database. You can flip in a new ssdl and mapping file without having to change the csdl.

     

    On the other hand, I guess you could also flip in a whole new edmx file, where the mapping and storage have been modified.

    Tuesday, September 4, 2007 4:13 PM
  • Craig,

     

    Please don't forget the test project as project to support.

     

    Cees

     

    Thursday, September 6, 2007 4:54 PM
  • Cees,

     

    I assume that you are talking about a Visual Studio unit test project?  Do you have a requirement to use an Entity model in a unit test project?

     

    Thanks.

    Thursday, September 6, 2007 5:04 PM
  • Craig,

     

    Your are right I am talking about VS unit test projects. I like, and with me I suppose many others, like to use unit tests.

     

    Some of the unit tests will run against a database filled with test data. I think it is necessary to have the Entity Model available to run this kind of tests. I see no other way. Do you?

     

    Cees

    Thursday, September 6, 2007 5:35 PM
  • I guess that you could also create a Class Library project and work on your model there and then share it with your unit test project.  This would be very useful if you find yourself wanting to use the same database among multiple test projects.

     

    Would this work for you or would you need an EDM model in the actual unit test project?

     

    I am not trying to pursuade you either way, just very interested in understanding how important these scenarios are to you.

     

    Thanks!

    Thursday, September 6, 2007 5:39 PM
  • Julie Lerman has a nice blog post explaining how to share Entity Framework projects among multiple projects that might be helpful for this as well.

     

    Thursday, September 6, 2007 5:58 PM
  • Graig,

     

    I'am not sure that I am precise enough. I mean the model metadata files. .csdl, .ssdl and .msl.

     

    In one of your replies you say:

     

    The three main project systems that we support each have their own way of telling the runtime where to find the C/M/S files that are generated during build.

     

    The three project types are Windows, Web and WebSite. You explain how you will handle the metadata files for these projects. My question is how will you handle this issue for Test projects.

     

    You suggestion to move to model (.emdx file) to a class library project is oke but that is already the case.

     

    The point is that in many of our tests, the connection is opened in the Unit Tests which are part of the test project. Therefore we need to know the path to the c/m/s files. Where will they be?

     

    Is this a real issue? At least for our way of working. But I think I is common to open the connection in the unit test for database oriented tests.

     

    Cees

     

    Thursday, September 6, 2007 8:16 PM
  •  

    Hey Cees,

     

    I don't have my VPC open but my memory tells me that the class project handles the location of the C/M/S files the same as a windows forms project does, in the bin folder.

     

    I would just create a test class library project, add an EDM to it and then go poke around to see what the results are.

     

    I'm not sure if you got a chance to look at my blog post that Tommy pointed to, but you can control where the three schema files are created when they are generated (see my post for how to do it). If you do this, you'll  need to modify the metadata parameters in the connection string of the config file in clsas library project so that it knows where you have 'moved' the files to.

     

    hth

     

    julie

    Monday, September 10, 2007 4:27 AM
  • Did you try |DataDirectory| (see my post earlier in this thread)? You can set that on the AppDomain of any type of application, and then use it in the connection string.

     

    Zlatko Michailov

    Program Manager, Data Programmability Runtime

    Microsoft Corp.

     

    Monday, September 10, 2007 3:50 PM
  • With your help and some testing I have found out how to copy the c/m/s files the the right directory in a test project.

     

    First of all a VS test project is in fact a class library project. When this type of project containing an .edmx file is build, the c/m/s file are created and copied the the /bin/debug directory. A connection string pointed to the c/m/s files is added to the app.config file. The app.config file is also copied on build to the /bin/debug directory and renamed to <appname>.dll.config.

     

    Copy of the c/m/s/ to the test directories located in de TestResults sub directory is the repsonsibility of the test frame work. Additional files to copy can be specified in the test configuration file, which can be edit. (VS menu: Test | Edit Test Run Configuration). Here can you specify that the c/m/s files must be copy the the TestResults directory.

     

    Thanks for your help Cees

    Monday, September 10, 2007 5:10 PM
  • I am incredibly unnerved that no one is really putting a lot of attention into Unit Tests. Smile

     

    The problem is not the pathing in the connection string.  The problem is that the external CSM files are not being copied to the Out directory for the Test Run to begin with.

     

    Unit Testing is HUGE!

     

    As a strong advocate of TDD, my very strong suggestion is to please ensure that EF supports test projects and ensures the necessary/correct files are copied correctly to the Test Run folder w/o any configuration on the user's side.

     

    Thanks. Smile

    Wednesday, September 12, 2007 2:40 AM
  • MichaelD_: wonderful! You set me on the track.

    metadata=../../../; works like a dream in the connection string config file of my unit tests. (I keep the csdl, msl and ssdl at solution root.)
    I thought unit tests executed in the same directory as vshost.exe or something, but of course they execute in their test "out" folder.

    Lars-Erik


    Lars-Erik
    Monday, February 2, 2009 11:54 AM