场景:
我有一个 C#Winforms 应用程序,该应用程序使用 EF6 DB-first 方法和一个 MySQL 数据库,该数据库将使用 ClickOnce 。
该应用程序需要什么:
具有可配置的连接字符串。
我要做什么:
用于保留ClickOnce更新之间的设置,并且该设置适用于“常规”设置,连接字符串除外。现在我们都知道,将ADO.NET模型用于EF6时,连接字符串保存在app.config(或web.config)的 <connectionStrings>
部分中,该部分为保存在[app].exe.config
(位于ClickOnce部署目录中)之间的ClickOnce更新之间丢失。
我敢保证:(我也测试过)
Project Properties → Settings)
中的值在ClickOnce更新之间会保留或迁移,app.config
的{{1}}或<appSettings>
部分中的注意:
我已经以一种单独的类库的方式对解决方案进行了分层,该类库包含正在消耗的<connectionStrings>
和UserControl
(因为预计其他项目也会使用它)并由Winforms主项目的Form
调用。
我尝试做的事情:
紧跟what was said in this answer,尤其是选项A和C。请注意,该链接中的选项B对我来说不是一个选项,因为它需要使用Program.cs
方法。
对于其他选项,我尝试了两者和C, AND 两者的组合,但仍然遇到“不支持关键字服务器”的异常。请参考以下示例代码:
<connectionStrings>
请注意,app.config的显着部分在我的解决方案的各层(数据层,UI类库,winforms项目)之间是相似的,尤其是// snippet portion from a "test connection" functionality
using (var db = new MySampleDbContext(MyCustomMySQLEFConnectionString))
{
await db.Database.Connection.OpenAsync(); // the above exception occurs in this line
}
部分和<entityFramework>
。请参阅以下有关配置文件的部分:
<connectionStrings>
我还尝试将 <entityFramework>
<defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6"></defaultConnectionFactory>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
</entityFramework>
<connectionStrings>
<add name="sampleEntities" connectionString="metadata=res://*/SampleModel.csdl|res://*/SampleModel.ssdl|res://*/SampleModel.msl;provider=MySql.Data.MySqlClient;provider connection string="server=localhost;user id=myuserid;password=mypassword;persistsecurityinfo=True;database=mydatabase"" providerName="System.Data.EntityClient" />
</connectionStrings>
的属性从上面的providerName
更改为System.Data.EntityClient
,并抛出了另一个MySql.Data.MySqlClient
。这是触发我异常代码的一部分的堆栈跟踪:
ArgumentException
该代码为:
Option not supported.
Parameter name: metadata
Stack trace: at MySql.Data.MySqlClient.MySqlConnectionStringBuilder.GetOption(String key)
at MySql.Data.MySqlClient.MySqlConnectionStringBuilder.set_Item(String keyword, Object value)
at System.Data.Common.DbConnectionStringBuilder.set_ConnectionString(String value)
at MySql.Data.MySqlClient.MySqlConnectionStringBuilder..ctor(String connStr)
at MySql.Data.MySqlClient.MySqlConnection.set_ConnectionString(String value)
at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.<SetConnectionString>b__18(DbConnection t, DbConnectionPropertyInterceptionContext``1 c)
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher``1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action``2 operation, TInterceptionContext interceptionContext, Action``3 executing, Action``3 executed)
at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.SetConnectionString(DbConnection connection, DbConnectionPropertyInterceptionContext``1 interceptionContext)
at System.Data.Entity.Internal.LazyInternalConnection.InitializeFromConnectionStringSetting(ConnectionStringSettings appConfigConnection)
at System.Data.Entity.Internal.LazyInternalConnection.TryInitializeFromAppConfig(String name, AppConfig config)
at System.Data.Entity.Internal.LazyInternalConnection.Initialize()
at System.Data.Entity.Internal.LazyInternalConnection.get_Connection()
at System.Data.Entity.Internal.LazyInternalContext.get_Connection()
at System.Data.Entity.Database.get_Connection()
at MyProjectNamespace.MyCodeFile.SampleMethod() in D:\ProjectFolder\MyCodeFile.cs:line 125...
其中,在我的应用程序保存的自定义连接字符串丢失的情况下,我尝试提供默认的连接字符串。顺便说一句,我的解决方法 // calling parameterless DbContext constructor
using (var db = new MySampleDbContext())
{
defaultConnection = db.Database.Connection.ConnectionString; // this line triggers the above exception
}
不能在ClickOnce更新时迁移,并具有可配置的连接字符串,这是考虑到注释in another SO answer生成的包含连接字符串的加密文件。
问题:
我应该如何正确实现可配置的EF连接字符串,该设置值在两次ClickOnce更新之间应该是安全的,并且不会遇到此“关键字不受支持”例外?