实体框架和配置.从静态上下文中调用

本文关键字:上下文 调用 静态 框架 配置 实体 | 更新日期: 2023-09-27 18:14:53

我开始想使用T4生成代码。要做到这一点,我需要从数据库的数据。因为项目中的所有数据都已经使用EF检索过了,所以我选择使用EF。因此,在我的项目中,我创建了一个带有静态方法的实用程序类,该方法返回我需要的对象。我发现,在T4自定义工具的上下文中运行,我无法从配置中读取。所以我手动设置了上下文的connectionstring,它工作了!

    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;
    }

后来,我在我的解决方案中添加了一个项目。Project A保存带有返回对象的静态方法的类。现在,从项目B中的代码中,我希望调用该静态方法。

当运行该代码时,我得到一个错误:"没有为ADO找到实体框架提供程序。. NET提供程序具有不变名称'System.Data.SqlClient'。确保在应用程序配置文件的"entityFramework"部分中注册了提供程序。"

当我为项目B安装nuget包EF时,代码按预期运行。但这违背了在项目 a 中创建实用程序类的全部目的。调用方应该只接收对象,而不考虑其自身的上下文。

我该如何解决这个问题?我如何配置一个静态方法来使用EF,并使它可用作调用方的引用,而不知道EF?

我认为答案可能是重写EF行为,从实用程序类中提供的静态上下文中读取,而不是当前运行时提供的配置。但你怎么能这么做呢?

实体框架和配置.从静态上下文中调用

如果您不想添加整个EF包,那么只需在项目b中添加对EntityFramework.SqlServer.dll的引用。

即使项目B引用了项目A,它也不会复制这个文件,因为它在EF Section的配置文件中被引用了。

 <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>

参见上面的providers部分,它告诉实体框架在哪里找到你正在使用的provider (System.Data.SqlClient)

关于T4模板的第一部分,我能够通过手动设置connectionstring来解决:

    /// <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;
    }

我使用那个connectionstring创建了一个System.Data.Entity.DbContext,并将它提供给GenericUnitOfWork。现在T4可以正常运行我的getData方法了。

当我从另一个项目调用getData方法时,我提供connectionstring作为参数。但是,getData方法只有在调用程序集知道EntityFramework作为引用的情况下才能正常运行。

所以我在另一个项目中添加了对EF的引用。

但我仍然不满意:如何配置我的getData方法,调用程序集不需要有对EF的引用?我是说这应该是可能的,对吧?