Entity framework 和配置。从静态上下文调用
Entity framework and configuration. Calling from static context
我开始想使用 T4 生成代码。为此,我需要来自数据库的数据。由于项目中的所有数据都已使用 EF 检索,因此我选择使用 EF。
因此,在我的项目中,我创建了一个实用程序 class,其中包含一个 returns 我需要的对象的静态方法。我发现,在 T4 自定义工具的上下文中,我无法从配置中读取 运行。所以我手动设置了我的上下文的连接字符串并且它起作用了!
private static string GetConnectionString()
{
//How to read from the web.config when running a T4 template ?
//ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["XXXXXXX"];
//var connectionString = settings.ConnectionString;
var connectionString = @"Data Source=XXXXXX;Initial Catalog=XXXXXX;Integrated Security=SSPI;MultipleActiveResultSets=true;";
return connectionString;
}
后来我在我的解决方案中添加了一个项目。项目 A 持有 class 和 returns 对象的静态方法。现在从项目 B 中的代码我希望调用该静态方法。
当 运行 该代码时,我得到一个错误:“没有 Entity Framework 为具有固定名称 'System.Data.SqlClient' 的 ADO.NET 提供程序找到提供程序。使确保提供商已在应用程序配置文件的 'entityFramework' 部分中注册。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=260882。"
当我为项目 B 安装 nuget 包 EF 时,代码按预期运行。
但这超出了在项目 A 中创建实用程序 class 的全部目的。
调用方应该只接收对象而不考虑它自己的上下文。
我该如何解决这个问题? 如何配置静态方法以使用 EF 并使其可供调用方参考使用,而不了解 EF?
我认为答案可能类似于覆盖 EF 行为以从实用程序 class 中提供的静态上下文而不是当前运行时提供的配置中读取。但是你怎么能这样做呢?
关于 T4 模板的第一部分,我能够通过手动设置连接字符串来解决:
/// <summary>
/// When calling from a T4 template, it seems you cannot use the ConfigurationManager.
/// </summary>
/// <returns></returns>
private static string GetConnectionString()
{
var connectionString = string.Empty;
if (ConfigurationManager.ConnectionStrings["DBContext"] != null)
{
connectionString = ConfigurationManager.ConnectionStrings["DBContext"].ConnectionString;
}
else if (System.Reflection.Assembly.GetExecutingAssembly().GetName().Name == "MyApplication")
{
ExeConfigurationFileMap configToUse = null;
var possibleConfig = System.Reflection.Assembly.GetExecutingAssembly().Location + ".config";
if (File.Exists(possibleConfig))
{
configToUse = new ExeConfigurationFileMap();
configToUse.ExeConfigFilename = possibleConfig;
var config = ConfigurationManager.OpenMappedExeConfiguration(configToUse, ConfigurationUserLevel.None);
connectionString = config.ConnectionStrings.ConnectionStrings["DBContext"].ConnectionString;
}
}
return connectionString;
}
我使用该连接字符串创建了一个 System.Data.Entity.DbContext 并将其提供给 GenericUnitOfWork。
现在 T4 能够 运行 我的 getData 方法正确。
当我从另一个项目调用 getData 方法时,我提供了连接字符串作为参数。
但是如果调用程序集知道 EntityFramework 作为参考,getData 方法仍然只会正确 运行 。
所以我在另一个项目中添加了对 EF 的引用。并且有效。
但我仍然不满意:如何配置调用程序集不需要引用 EF 的 getData 方法?我的意思是应该可以吧?
如果您不想添加整个 EF 包,则只需在项目 B 中添加对 EntityFramework.SqlServer.dll 的引用。
即使项目 B 引用项目 A,它也不会复制此文件,因为它在 EF 部分的配置文件中被引用。
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
参见上面的供应商部分,这告诉 entity framework 在哪里可以找到您正在使用的供应商 (System.Data.SqlClient)
我开始想使用 T4 生成代码。为此,我需要来自数据库的数据。由于项目中的所有数据都已使用 EF 检索,因此我选择使用 EF。 因此,在我的项目中,我创建了一个实用程序 class,其中包含一个 returns 我需要的对象的静态方法。我发现,在 T4 自定义工具的上下文中,我无法从配置中读取 运行。所以我手动设置了我的上下文的连接字符串并且它起作用了!
private static string GetConnectionString()
{
//How to read from the web.config when running a T4 template ?
//ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["XXXXXXX"];
//var connectionString = settings.ConnectionString;
var connectionString = @"Data Source=XXXXXX;Initial Catalog=XXXXXX;Integrated Security=SSPI;MultipleActiveResultSets=true;";
return connectionString;
}
后来我在我的解决方案中添加了一个项目。项目 A 持有 class 和 returns 对象的静态方法。现在从项目 B 中的代码我希望调用该静态方法。
当 运行 该代码时,我得到一个错误:“没有 Entity Framework 为具有固定名称 'System.Data.SqlClient' 的 ADO.NET 提供程序找到提供程序。使确保提供商已在应用程序配置文件的 'entityFramework' 部分中注册。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=260882。"
当我为项目 B 安装 nuget 包 EF 时,代码按预期运行。 但这超出了在项目 A 中创建实用程序 class 的全部目的。 调用方应该只接收对象而不考虑它自己的上下文。
我该如何解决这个问题? 如何配置静态方法以使用 EF 并使其可供调用方参考使用,而不了解 EF?
我认为答案可能类似于覆盖 EF 行为以从实用程序 class 中提供的静态上下文而不是当前运行时提供的配置中读取。但是你怎么能这样做呢?
关于 T4 模板的第一部分,我能够通过手动设置连接字符串来解决:
/// <summary>
/// When calling from a T4 template, it seems you cannot use the ConfigurationManager.
/// </summary>
/// <returns></returns>
private static string GetConnectionString()
{
var connectionString = string.Empty;
if (ConfigurationManager.ConnectionStrings["DBContext"] != null)
{
connectionString = ConfigurationManager.ConnectionStrings["DBContext"].ConnectionString;
}
else if (System.Reflection.Assembly.GetExecutingAssembly().GetName().Name == "MyApplication")
{
ExeConfigurationFileMap configToUse = null;
var possibleConfig = System.Reflection.Assembly.GetExecutingAssembly().Location + ".config";
if (File.Exists(possibleConfig))
{
configToUse = new ExeConfigurationFileMap();
configToUse.ExeConfigFilename = possibleConfig;
var config = ConfigurationManager.OpenMappedExeConfiguration(configToUse, ConfigurationUserLevel.None);
connectionString = config.ConnectionStrings.ConnectionStrings["DBContext"].ConnectionString;
}
}
return connectionString;
}
我使用该连接字符串创建了一个 System.Data.Entity.DbContext 并将其提供给 GenericUnitOfWork。 现在 T4 能够 运行 我的 getData 方法正确。
当我从另一个项目调用 getData 方法时,我提供了连接字符串作为参数。 但是如果调用程序集知道 EntityFramework 作为参考,getData 方法仍然只会正确 运行 。
所以我在另一个项目中添加了对 EF 的引用。并且有效。
但我仍然不满意:如何配置调用程序集不需要引用 EF 的 getData 方法?我的意思是应该可以吧?
如果您不想添加整个 EF 包,则只需在项目 B 中添加对 EntityFramework.SqlServer.dll 的引用。
即使项目 B 引用项目 A,它也不会复制此文件,因为它在 EF 部分的配置文件中被引用。
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
参见上面的供应商部分,这告诉 entity framework 在哪里可以找到您正在使用的供应商 (System.Data.SqlClient)