MetadataException - Unable to load the specified metadata resource? - c#

I have a solution with two relevant projects. The first builds My.exe, and the second builds a class library MyModel.dll that contains only my EF model.
I'm getting a MetadataException in my Model's VS-generated ObjectContext ctor. I've read through Troubleshooting Entity Framework Connection Strings, but I still haven't been able to narrow down my problem.
The offending constructor code:
public MyEntities() :
base(#"name=MyEntities", "MyEntities") // MetadataException here
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
Metadata Artifact Processing is set to EmbedInOutputAssembly. When I open MyModel.dll in Reflector, I see:
DataAccessLayer.MyModel.csdl
DataAccessLayer.MyModel.msl
DataAccessLayer.MyModel.ssdl
I've tried setting Build Action for my app.config to None and Content, and neither makes a difference. The config file contains:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="MyEntities"
connectionString="metadata=
res://*/DataAccessLayer.MyModel.csdl|
res://*/DataAccessLayer.MyModel.ssdl|
res://*/DataAccessLayer.MyModel.msl;
provider=Devart.Data.PostgreSql;
provider connection string="
User Id=MY_USER;
Password=MY_PASS;
Host=127.0.0.1;
Database=MY_DB;
Persist Security Info=True""
providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
I've tried replacing the resource prefix res://*/ with both res://MyModel.dll/ and res://MyModel/, leaving the rest intact (because it matches the resources in MyModel.dll), but neither solved the problem. My class library is strong-named.
Both my executable and class library projects contain references to System.Data.Entity and Devart.Data.PostgreSql, and My.dll is being built to the same location as My.exe.

I stepped into .NET source code, and by examining the arguments & local variables of internal EF calls, found the resource assembly name was still set to *.
It turns out a bug in my application code set the model's default connection string before calling the ObjectContext ctor. It was pulled from a Settings.settings file, which hadn't been recently sync'd with the latest, correct app.config.
Some reflections on our discussion in the comments:
The correct assembly name in app.config is MyModel rather than MyModel.dll (as shown in Craig's article.) Using MyModel.dll produces an exception in the EF code.
Calling the ctor as base(#"name=MyEntities") instead of base(#"name=MyEntities", "MyEntities") actually produced a new exception in ObjectContext.GetEntitySetName()
I updated Settings.settings to be in sync with app.config, and everything is now working.

Related

Entity Developer/EntityFramework - The specified named connection is either not found in the configuration

Using Devart Entity Developer with Entity Framework 6. I have my main class library project. I had a different Winform project altogether that uses Entity Developer/Entity Framework that I developed to do some database work with Sql. I decided to add this secondary Winform project to the main class library.
First I tried adding the Winform project to the solution. That did not work well. Even though I added a reference to the exe of the Winform project it seems not to find it ok. I removed that project from the solution.
As a second attempt. I copied the classes from the Winform project (two of them) to the main class library project and recreated the Entity Developer/Entity Framework stuff. Now when I run the project everything runs (including the new form) but I cannot connect to the database. I get the error:
The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid.
The line that has the error is the line calling base:
public SWPDMEngVaultEntities() :
base(#"name=SWPDMEngVaultEntitiesConnectionString", "SWPDMEngVaultEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
My connection string is in the app.config file and looks like this:
<connectionStrings>
<add name="SWPDMEngVaultEntitiesConnectionString" connectionString="metadata=res://*/DataModel1.csdl|res://*/DataModel1.ssdl|res://*/DataModel1.msl;provider=System.Data.SqlClient;provider connection string="Data Source=XXXXXX\SQLEXPRESS;Initial Catalog=XXXXXX;Integrated Security=False;Persist Security Info=True;User ID=XXXXXX;Password=XXXXXX""
providerName="System.Data.EntityClient" />
</connectionStrings>
All of the XXXXXX's in the above string have been confirmed as correct. Also, Entity Developer has a "Test Connection" and the test connection connects just fine. Entity Developer also gets the database information OK so I know it is able to connect without issue. The problem is at runtime on the solution.
I have looked at other posts about this error and they all seem to be saying make sure your connection string is good. What else should I check?
The answer to this issue came from Devart. Class libraries do not use app.config files for settings. By default the connection string in the Devary generated templates are stored in the app.config file. There is a place to turn this off when the model is generated.

Visual Studio Online Build - web.config connection strings configSource

My project Web.config has connection strings defined in a separate file using the following construct:
<connectionStrings configSource="ConnectionStrings.config">
</connectionStrings>
This is handy when collaborating on a project or when deploying the project. However, I was unable to get the VSO Build working as it shows me the following error:
C:\Program Files
(x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets (4105,
5) Could not copy the file
"C:\a\1\s\MyProject\ConnectionStrings.config" because it was not
found.
The connection string must be already defined in the web.config and the connection string name must be the same as the connection string name you set in Azure. Then the connection string can be updated by Azure. Refer to the description from Azure:
Connection strings work in a similar fashion, with a small additional
requirement. Remember from earlier that there is a connection string
called “example-config_db” that has been associated with the website.
If the website’s web.config file references the same connection string
in the configuration section, then Windows Azure
Web Sites will automatically update the connection string at runtime
using the value shown in the portal.
However, if Windows Azure Web Sites cannot find a connection string
with a matching name from the web.config, then the connection string
entered in the portal will only be available as an environment
variable (as shown earlier).
And
Remember though that for Windows Azure Web Sites to override a
connection string and materialize it in the .NET Framework’s
connection string configuration collection, the connection string must
already be defined in the web.config. For this example website, the
web.config has been updated as shown below:
For more information, please see this link: https://azure.microsoft.com/en-us/blog/windows-azure-web-sites-how-application-strings-and-connection-strings-work/
I know you already mark your question answered but I think I should post my solution here for anyone's having same issue.
I create a transformation for the connectionStrings section in other environment with a dummy connectionstring value like this:
<connectionStrings xdt:Transform="Replace">
<add name="Your_ConnectionString_Name" connectionString="dummy_value"
providerName="System.Data.SqlClient" />
</connectionStrings>
so that I can keep the configSource attribute in my local machine and when I deploy to other environments, I have some dummy connectionstring for Azure to replace.

Connectionstring in web.config wont work. Not even with absolute path

I've created a local database in Visual Studio with entity framework. But I can't get it to work. I get the "The underlying provider failed on Open."
I've tried with relative path to the database and absolute path but it wont work.
The project is MVC and the database is in an other solution in the project. (DataAccess > Logic < MVC)
The error I get when I run with absolute path. The error is the same with relative path:
"An attempt to attach an auto-named database for file ~D:\\Visual Studio Projects\\Esport\\Esport.Domain\\Context\\Database\\esportDatabase.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share."}"
My web.config in MVC:
<connectionStrings>
<add name="esportDatabaseEntities" connectionString="metadata=res://*/Context.Model.esportDatabaseModel.csdl|res://*/Context.Model.esportDatabaseModel.ssdl|res://*/Context.Model.esportDatabaseModel.msl;provider=System.Data.SqlClient;provider connection string="data source=(LocalDB)\v11.0;attachdbfilename=~D:\Visual Studio Projects\Esport\Esport.Domain\Context\Database\esportDatabase.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
My App.Config in DataAccess layer:
<connectionStrings>
<add name="esportDatabaseEntities" connectionString="metadata=res://*/Context.Model.esportDatabaseModel.csdl|res://*/Context.Model.esportDatabaseModel.ssdl|res://*/Context.Model.esportDatabaseModel.msl;provider=System.Data.SqlClient;provider connection string="data source=(LocalDB)\v11.0;attachdbfilename=|DataDirectory|\Context\Database\esportDatabase.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
EDIT: I moved the project to C: to get read and write and now it works with the absolute path. The problem is that I can't run it with absolute path. I need it to be relative. Any ideas how to do that? |DataDiretory| points to App_data and my database is not in app data..
EDIT2: When I run the relative path, |DataDiretory|esportDatabase.mdf I get this error:
{"An attempt to attach an auto-named database for file C:\\Esport\\Esport\\App_Data\\Context\\Database\\esportDatabase.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share."}
But the database is not located there. Its located at: C:\Esport\Esport.Domain\Context\Database\esportDatabase.mdf.
I have found that using code based configuration for EF is much easier to work with.
To gain complete control over what goes on with the connection string, you can create a special constructor for your DbContext derived classes that takes a connection string argument, and then use your constructor with a connection string every time you instantiate your DbContext classes.
The EF templates generate the DbContext derived classes as partial classes, which means you can add this constructor away from the auto-generated code.
It is fully explained here:
http://www.programmersranch.com/2013/11/c-ef-setting-connection-strings-at.html
FYI, you can manipulate DataDirectory like this, though you should be careful about how it could affect other parts of your application:
string AppDomainDataDirectory
{
get
{
object obj = AppDomain.CurrentDomain.GetData("DataDirectory");
return obj != null ? obj.ToString() : "";
}
set
{
AppDomain.CurrentDomain.SetData("DataDirectory", value);
}
}

System.Data.SqLite DataProvider not found when executing Test using NUnit

I am facing a problem with my UnitTest. I want to Test my Data-Access which is done using a repository based on NPoco. I have therefore written a couple of tests and the test project retrieves NUnit, NPoco, System.Data.SQLite, and some other Stuff via NuGet.
This is the app.config of the TestProject:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="RepositoryTests.Properties.Settings.ConnectionString" connectionString="Data Source=db.sqlite;Version=3" />
</connectionStrings>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite"/>
<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
</system.data>
</configuration>
In VS, the Project builds fine. Triggering the tests in Visual Studio works as well.
Building the Projects with MSBUILD works as well. Running the tests via nunit after building them with msbuild.exe raises a Exception though:
Unable to find the requested .Net Framework Data Provider. It may not be installed.
This is only the case, when executing the tests using nunit directly (sth. like nunit-console.exe myproject.csproj /config:Release). Triggering them in VS is no problem.
Does anybody know how to solve this problem?
The problem is caused by the nunit test runner having its own app.config in which your settings are not present.
The simplest way to solve the problem is to move the configuration out of your app.config and into the code itself. Whatever you have in app.config can be done inside code.
Another solution is to move the configuration into a seperate file and then explicitly load that file's configuration using code. Just make sure that the file is copied to the output folder on build.
You could use something like:
public static class TestFactory
{
public static DatabaseFactory DbFactory { get; set; }
public static void Setup()
{
var fluentConfig = FluentMappingConfiguration.Configure(new OurMappings());
//or individual mappings
//var fluentConfig = FluentMappingConfiguration.Configure(new UserMapping(), ....);
DbFactory = DatabaseFactory.Config(x =>
{
// Load the connection string here or just use a constant in code...
x.UsingDatabase(() => new Database("connString");
x.WithFluentConfig(fluentConfig);
x.WithMapper(new Mapper());
});
}
}
See here for more details.
Then in the test fixture:
[TestFixture]
public class DbTestFixture
{
[TestFixtureSetUp]
public void Init()
{
TestFactory.Setup();
}
[Test]
public void YourTestHere()
{
var database = TestFactory.DbFactory.GetDatabase();
...
}
}
I got it working by creating an copy of the app.config-file and give that copy the name of the Test-Project, followed by .config. So if we assume, that the project is named Test.Project the copy must be named Test.Project.config. Nunit doesn't seem to load the automatically generated Test.Project.dll.config. This info can be found somewhat disguised in the NUnit-docs (Configuration Files -> Test Configuration File -> 3rd paragraph, last sentence).
In VS, in the Properties-Section of that copied file, i set the copy-to-output-directory-property to always.
Executing the tests with nunit-console.exe then lead to another exception (Bad-Image), which was caused by NUnit not finding the SQLite.Interop.dll-file. This could be solved kind of hacky by adding that file, which already resides in the x64 or x86 folder, as an existing element to the solution in VS and also setting the copy-to-output-dir-property to always.

Get connection string using app.config file in C#

I want to get connection string using app.config file
this is my app.config file :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="MSSConStr"
connectionString="Data Source=Sithi-PC;Initial Catalog=mssdb2;User ID=XXXXX;Password=YYYYYYY"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
string x = ConfigurationManager.ConnectionStrings["MSSConStr"].ConnectionString;
this statement gives a exception "Object reference not set to an instance of an object."
Please can u help me to correct this error!!! this is working properly in .NET framework 3.5 project. But this project is .NET framework 4.0. I added the reference "System.Configuration" to my project and use it in my Database Access class.
Thank you!!!
EDIT: Addional Code:
public static SqlConnection getNewConnection()
{
string x = ConfigurationManager.ConnectionStrings["MSSConStr"].ConnectionString.ToString();
con2 = new SqlConnection(x);
return con2;
}
There are two possible issues:
1) You have some settings elsewhere in the app (settings, code, etc, that is unintentionally clearing the connection strings (unlikely, but possible).
2) The .config that is being used at run time does not have the connection string propagated to it. If you are running in debug mode, open windows explorer, navigate to the bin/debug directory and open the .exe.config or .vshost.exe.config file and see if the connection string is set correctly there. If it isn't, stop the application, clear the directory, and try again. If the problem persists, see item #1.

Categories