简体   繁体   English

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

[英]Entity framework and configuration. Calling from static context

I started wanting to generate code using T4. 我开始想要使用T4生成代码。 To do this I need data from database. 为此,我需要来自数据库的数据。 Since all data within the project is already retrieved using EF, I choose to use EF. 由于项目中的所有数据均已使用EF检索,因此我选择使用EF。 So within my project I created a utility class with a static method that returns the object I need. 因此,在我的项目中,我创建了一个带有静态方法的实用程序类,该方法返回我需要的对象。 I found out, that running in the context of the T4 custom tool I cannot read from config. 我发现,在无法从config读取的T4定制工具的上下文中运行。 So I manually set the connectionstring of my context and it worked! 因此,我手动设置了上下文的连接字符串,它起作用了!

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

Later on I added a project to my solution. 稍后,我在解决方案中添加了一个项目。 Project A holds the class with the static method that returns an object. 项目A使用返回对象的静态方法保存该类。 Now from code in Project B I wish to call that static method. 现在,从项目B中的代码中,我希望调用该静态方法。

When running that code I get an error: " No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlClient'. Make sure the provider is registered in the 'entityFramework' section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information. " 运行该代码时,出现错误消息:“未找到具有不变名称'System.Data.SqlClient'的ADO.NET提供程序的实体框架提供程序。请确保该提供程序已在应用程序配置文件的'entityFramework'部分中注册。有关更多信息,请参见http://go.microsoft.com/fwlink/?LinkId=260882

When I install nuget package EF for project B , the code runs as expected. 当我为项目B安装nuget软件包EF时,代码将按预期运行。 But this beats the whole purpose of creating a utility class in project A . 但这超出了在项目A中创建实用程序类的全部目的。 The calling party should just receive the object regardless of its own context. 主叫方应该只接收对象,而不管其自身的上下文如何。

How can I fix this? 我怎样才能解决这个问题? How can I configure a static method to use EF and make it available for usage as a reference to calling parties, not knowing EF? 如何配置静态方法以使用EF并使其可用作不知道EF的呼叫方的参考?

I think the answer will probably be something like overriding EF behaviour to read from the static context provided in the utility class instead of the configuration provided by current runtime. 我认为答案可能类似于重写EF行为,以便从实用程序类提供的静态上下文中读取,而不是从当前运行时提供的配置中读取。 But how can you do this? 但是,您该怎么办呢?

If you don't want to add the whole EF package then just add a reference to EntityFramework.SqlServer.dll in Project B. 如果您不想添加整个EF包,则只需在Project B中添加对EntityFramework.SqlServer.dll的引用。

Even though Project B references Project A it will not copy this file over because it is referenced in the config file in the EF Section. 即使项目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>

See the providers section above, this tells entity framework where to find the provider your are using (System.Data.SqlClient) 请参阅上面的提供程序部分,它告诉实体框架在哪里可以找到您正在使用的提供程序(System.Data.SqlClient)

The first part regarding the T4 template, I was able to resolve by setting the connectionstring manually: 关于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;
    }

I create a System.Data.Entity.DbContext using that connectionstring and feed it to the GenericUnitOfWork. 我使用该连接字符串创建一个System.Data.Entity.DbContext并将其提供给GenericUnitOfWork。 Now the T4 is able to run my getData method properly. 现在,T4能够正确运行我的getData方法。

When I call the getData method from another project I provide the connectionstring as a parameter. 当我从另一个项目中调用getData方法时,我提供了连接字符串作为参数。 But still the getData method will only run properly if the calling assembly knows EntityFramework as a reference. 但是,只有在调用程序集知道EntityFramework作为引用的情况下,getData方法仍将正确运行。

So I added a reference to EF in the other project. 因此,我在另一个项目中添加了对EF的引用。 And it works. 而且有效。

But I am still not satisfied: how to configure my getData method that the calling assembly does not need to have a reference to EF? 但是我仍然不满意:如何配置我的getData方法,使调用程序集不需要引用EF? I mean that should be possible right? 我的意思是应该可行吧?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM