How to integrate SQL Server CE with Enterprise Library 5 DatabaseFactory? - c#

I'm getting an
"Activation error occured while trying to get instance of type
Database, key "" "
exception with my DatabaseFactory.CreateDatabase() whenever I reference the default database to a SQL Server CE
I tried checking if the problem is just my .dll reference, which I was able to prove wrong because I was still able to connect to a real SQL Server 2008 db.
Here's my config:
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false"/>
</configSections>
<dataConfiguration defaultDatabase="sqlCEDB"/>
<connectionStrings>
<add name="sqlCEDB"
connectionString="Data Source=|DataDirectory|\sqlCEDB.sdf;Password='somepassword'"
providerName="Microsoft.SqlServerCe.Client.3.5" />
</connectionStrings>
Here's how I create the database instance:
private Database db;
protected internal Database DB
{
get
{
if (db == null)
db = DatabaseFactory.CreateDatabase();
return db;
}
}
SOLUTION
change config property
solved: providerName="System.Data.SqlServerCe.3.5"

SOLUTION
change config property solved: providerName="System.Data.SqlServerCe.3.5"
<configSections>
<section name="dataConfiguration"
type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="false"/>
</configSections>
<dataConfiguration defaultDatabase="sqlCEDB"/>
<connectionStrings>
<add name="sqlCEDB"
connectionString="Data Source=|DataDirectory|\sqlCEDB.sdf;Password='somepassword'"
providerName="System.Data.SqlServerCe.3.5" />
</connectionStrings>

Related

Read appSettings section from Web.config file using WebConfigurationManager

I'm developing a WinForm application with C# and .NET Framework 4.7.
I want to open a Web.config file, read its appSetting section and modify it.
To open it, I use this:
System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration(null);
It opens it but, when I try to get the keys with:
string[] keys = config.AppSettings.Settings.AllKeys;
I get a null array.
This is the appSetting section:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="MinRemainingCodes" value="100" />
<!-- Others keys -->
</appSettings>
</configuration>
Maybe the problem is that it is not opening the file, but in the documentation say:
The virtual path to the configuration file. If null, the root
Web.config file is opened.
Maybe I don't understand what means with root because the program and the Web.config file are in the same folder.
What am I doing wrong?
WebConfigurationManager.OpenWebConfiguration includes the following description of the path parameter:
The virtual path to the configuration file. If null, the root Web.config file is opened.
Because your application is not running under IIS as a Web Site, the Web.config that is being opened is actually that which lives in the .NET Framework installation folder itself (in my case, that's C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config).
WebConfigurationManager.OpenMappedWebConfiguration allows you to map virtual directories to physical directories in order to allow you to specify a virtual path that is mapped to your own local directory. Here's the code I've used to make this work:
var webConfigurationFileMap = new WebConfigurationFileMap();
webConfigurationFileMap.VirtualDirectories.Add(
string.Empty,
new VirtualDirectoryMapping(Directory.GetCurrentDirectory(), isAppRoot: true));
var webConfig = WebConfigurationManager.OpenMappedWebConfiguration(
webConfigurationFileMap,
string.Empty);
As you can see, I'm mapping the root virtual directory (using string.Empty) to the application's directory (using Directory.GetCurrentDirectory).
OpenWebConfiguration is supposed to receive the path to your web config if I'm not mistaken and you are passing it null.
Try like this:
config = WebConfigurationManager.OpenWebConfiguration("~");
Also this might help you: How do you modify the web.config appSettings at runtime?
Well, first of all, you use web.config for a desktop application. It doesn't sound correct. Try to use app.config instead.
Second, WebConfigurationManager.OpenWebConfiguration opens the Web-application configuration file
As for the topic, to get information from the config file try to use
var keys = ConfigurationManager.AppSettings.AllKeys

How to configure Enterpise Library 6.0 logging to database?

In my App.config I have a second things:
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<dataConfiguration defaultDatabase="Core" />
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
<listeners>
<add name="Database Trace Listener"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
databaseInstanceName="Core"
writeLogStoredProcName="WriteLog"
addCategoryStoredProcName="AddCategory" />
<add name="Rolling Flat File Trace Listener"
type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
fileName="rolling.log"
formatter="Text Formatter"
rollInterval="Hour"
rollSizeKB="10000"
traceOutputOptions="DateTime, Callstack" />
</listeners>
<formatters>
<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
template="Application: {property(ApplicationName)}{newline}
Guid: {property(HandlingInstanceId)}{newline}
Timestamp: {timestamp}{newline}
Message: {message}{newline}
Exception type: {property(ExceptionType)}{newline}
Category: {category}{newline}
Severity: {severity}{newline}
Machine: {localMachine}{newline}
App Domain: {localAppDomain}{newline}
ProcessId: {localProcessId}{newline}
Process Name: {localProcessName}{newline}
Stack trace: {property(StackTrace)}{newline}
File: {property(FileName)}{newline}
Line: {property(LineNumber)}{newline}"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="General">
<listeners>
<add name="Database Trace Listener" />
<add name="Rolling Flat File Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events" />
<notProcessed switchValue="All" name="Unprocessed Category" />
<errors switchValue="All" name="Logging Errors & Warnings">
<listeners>
<add name="Database Trace Listener" />
<add name="Rolling Flat File Trace Listener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
I also added this part into initialisation:
DatabaseFactory.SetDatabaseProviderFactory(new DatabaseProviderFactory());
LogWriterFactory logWriterFactory = new LogWriterFactory();
And, Exception write:
private static void LogExceptionDetails(Exception ex)
{
LogEntry logEntry = new LogEntry
{
Message = ex.Message
};
Logger.Write(logEntry);
}
The thing I cant get so far is, how I suppose to detect, in which table exception will be logged.
I mean, to make Enterprise see Core, I need to add:
<connectionStrings>
<add name="Core" connectionString="blablabla" />
</connectionStrings>
But this still doest explain how to select propher table and format it (the only way I know is creating procedure and putting it in writeLogStoredProcName= but I used this in 4.1, I never touched 6.0 before).
Also, the problem is that all my confirugations are stored in another database, and this is the reason why I want to get rid of connectionString from App.config).
So, to summarize, my question is:
Is there a way to set database, table and table columns outside the App.config (and procedure) for Enterprise Library Logging to database? Maybe it is done somewhere in DatabaseFactory?
P.S Local logging into rolling.log file works fine.
EDIT: Looks like I have no choise and I need to use procedure to write in needed table. Still trying to find a way to set connectionstring outside the App.config
As you found out the out of the box FormattedDatabaseTraceListener writes to the database using a stored procedure. You can configure the name of the stored procedure but a stored procedure contains the database specific logic. You can modify or create a new stored procedure to do whatever you want as long as it conforms to the stored procedure interfaces:
CREATE PROCEDURE [dbo].[WriteLog]
(
#EventID int,
#Priority int,
#Severity nvarchar(32),
#Title nvarchar(256),
#Timestamp datetime,
#MachineName nvarchar(32),
#AppDomainName nvarchar(512),
#ProcessID nvarchar(256),
#ProcessName nvarchar(512),
#ThreadName nvarchar(512),
#Win32ThreadId nvarchar(128),
#Message nvarchar(1500),
#FormattedMessage ntext,
#LogId int OUTPUT
)
CREATE PROCEDURE [dbo].[AddCategory]
#CategoryName nvarchar(64),
#LogID int
The other alternative is to create a custom trace listener to do exactly what you want.
In terms of placing the connectionStrings in an external configuration file you can use the built-in .NET configSource attribute:
<connectionStrings configSource="connections.config" />
Or the Enterprise Library redirectSections:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<enterpriseLibrary.ConfigurationSource selectedSource="System Configuration Source">
<sources>
<add name="System Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add name="File-based Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
filePath="data.config" />
</sources>
<redirectSections>
<add sourceName="File-based Configuration Source" name="dataConfiguration" />
<add sourceName="File-based Configuration Source" name="connectionStrings" />
</redirectSections>
</enterpriseLibrary.ConfigurationSource>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
If you want to be completely app.config "independent" then you can place all configuration in an external configuration file and then load that configuration programmatically using a FileConfigurationSource.
See my answer to EnterpriseLibrary Data Access Application Block redirect Section can't find default database
for more details.
If you want to mix and match declarative XML logging configuration with runtime programmatic database configuration then you can do it using something similar to:
class Program
{
static void Main(string[] args)
{
// Configure databases from some external source but ensure that
// database name matches XML config
DatabaseFactory.SetDatabases(
() => CreateDatabaseFromExternalSource(null),
name => CreateDatabaseFromExternalSource(name));
// Configure logging from XML config
LogWriterFactory factory = new LogWriterFactory();
Logger.SetLogWriter(factory.Create());
Logger.Write("Test", "General");
}
private static Database CreateDatabaseFromExternalSource(string name)
{
// SqlDatabase assumes SQL Server database
return new SqlDatabase(GetConnectionString(name));
}
private static string GetConnectionString(string name)
{
// do whatever you need to get the database connection
return #"Server=.\SQLEXPRESS;Database=myDataBase;User Id=myUsername;Password=myPassword;";
}
}

WCF EntityFrameWork Exception in IIS

I need help configuring my WCF service that access a SQL database through EF. The service runs fine when I launch it locally through visual studio, but when I deploy it to another server and access it through my client application I keep getting "{"An error occurred while getting provider information from the database. This can be caused by Entity Framework using an incorrect connection string. Check the inner exceptions for details and ensure that the connection string is correct."}" error.
My Connection string before I publish the service to the server is:
<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>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
</entityFramework>
<connectionStrings>
<add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-ECUWebUi-20121116095239;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-ECUWebUi-20121116095239.mdf" />
</connectionStrings>
My Connection string after I publish:
<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>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
<connectionStrings>
<add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=localhost; Integrated Security=SSPI; Initial Catalog=ECUWeb-Staging;User ID=user;Password=password" />
</connectionStrings>
This is the call to the EF context in the service:
public RegisterResponse Register(RegisterRequest request)
{
EfDataAccessFactory factory = new EfDataAccessFactory(new DtoMapper());
RegisterResponse response = new RegisterResponse();
if (request.Computer.Exists())
{
factory.ComputerDataAccess.Update(request.Computer);
response.Message = string.Format("{0} is already registered.", request.Computer.Name);
}
else
{
request.Computer = factory.ComputerDataAccess.Insert(request.Computer);
response.Message = string.Format("{0} registered with id: {1}", request.Computer.Name, request.Computer.Id);
}
RegisterInstances(request);
return response;
}
Any suggestions? Also the Inner Exception is null.
Fixed it I had to add:
<add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=localhost;Initial Catalog=ECUWeb-Staging;User Id = user; Password = password" />
<add name="EcuWeb.Data.EcuWebDataContext" connectionString="Data Source=localhost;Initial Catalog=ECUWeb-Staging; User Id = user; Password = password" providerName="System.Data.SqlClient" />
Then it worked no problem.

Configuration system failed to initialise

I have a console application with a config file called app.config. The full code behind by app.config file is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ClientSettingsProvider.ServiceUri" value=""/>
<add key="Server" value="0.0.0.0"/>
<add key="DB" value="Test"/>
<add key="UserName" value="testuser"/>
<add key="Password" value="testuser"/>
<add key="AgentEmail" value="test#gmail.com"/>
</appSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
</configuration>
When I try to run my application, I get an error : Configuration system failed to initialize. Any idea what am I doing wrong?
Remove the configSections from the file if you don't require it.
You're defining a section group and a contained section in your config here:
<configuration>
<configSections>
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="LeadDataEmail.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
That means, there must be a <applicationSettings> container, with a contained <LeadDataEmail.Properties.Settings> XML element in your <configuration>:
<configuration>
<configSections>
......
</configSections>
<applicationSettings>
<LeadDataEmail.Properties.Settings
attribute1="value1"
attribute2="value2" />
</applicationSettings>
....
</configuration>
but I don't see any trace of that in your config file - no wonder the config system cannot initialize!

Why does ConfigurationManager.OpenMappedExeConfiguration have an extra connection string not in the file?

I'm unit testing my config file for a win forms application.
In the LocalTestRun.testrunconfig I set it to copy the app.config. I've checked the Environment.CurrentDirectory while the test was running and the file doesn't have this extra connection string either. This is the test method:
[TestMethod]
public void Configuration_ConnectionStrings_Connect()
{
Console.WriteLine(Environment.CurrentDirectory);
Assert.IsTrue(System.IO.File.Exists("App.Config"));
var configFileMap = new ExeConfigurationFileMap(){ ExeConfigFilename = "App.Config"};
var config= ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
foreach (ConnectionStringSettings connectionString in config.ConnectionStrings.ConnectionStrings)
{
//Assumes all connections are to Sql server, test must be updated if not
Assert.AreEqual("System.Data.SqlClient",connectionString.ProviderName,"Test was only designed for SQL clients");
using (var cn=new System.Data.SqlClient.SqlConnection(connectionString.ConnectionString))
{
cn.Open();
Assert.AreEqual(System.Data.ConnectionState.Open,cn.State);
}
}
}
However When I iterate the config.ConnectionStrings.ConnectionStrings I have an extra configuration string that is not in the file:
data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true
This isn't and never was an asp.net project.
Here's the config File:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="HLIT_Ticketing.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="HLIT_Ticketing.Properties.Settings.HomeQConnectionString"
connectionString="Data Source=******\*****;Initial Catalog=*****;Persist Security Info=True;User ID=*****;Password=******"
providerName="System.Data.SqlClient" />
</connectionStrings>
<userSettings>
<HLIT_Ticketing.Properties.Settings>
<setting name="AssociateRole" serializeAs="String">
<value>Associate</value>
</setting>
<setting name="DeveloperRole" serializeAs="String">
<value>Developer</value>
</setting>
</HLIT_Ticketing.Properties.Settings>
</userSettings>
Where is this extra connection string coming from?
That connection string is defined in the machine-level configuration file, machine.config.
If you look at the file C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config, you will see the following section:
<connectionStrings>
<add name="LocalSqlServer" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
Dave nailed the main answer - upvoted.
But: if you want to get rid of any connection string from the machine.config or any "up-stream" web.configs, you can always use:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<clear />
<add name="HLIT_Ticketing.Properties.Settings.HomeQConnectionString"
connectionString="Data Source=******\*****;Initial Catalog=*****;Persist Security Info=True;User ID=*****;Password=******"
providerName="System.Data.SqlClient" />
</connectionStrings>
That first <clear/> in the connection strings section wipes out any previously present connection strings and starts with a clean slate.

Categories