【问题标题】:Reading data embedded into a .NET assembly读取嵌入到 .NET 程序集中的数据
【发布时间】:2017-10-21 21:02:23
【问题描述】:

对于一个学校项目,我不允许使用存储过程来存储我的 SQL 脚本。为了解决这个问题,我尝试在我的班级程序集中创建一个 SQL_scripts 文件夹。

现在我不知道如何从相对路径读取我的脚本?

这是我尝试但没有成功的:

var appDomain = System.AppDomain.CurrentDomain;
                var basePath = appDomain.RelativeSearchPath ?? appDomain.BaseDirectory;
                string path = Path.Combine(basePath, "SQL_scriptes", "GetAllEmptyRoomsAtDateRange.sql");
                string query = File.ReadAllText(path);

但我总是在以下文件夹中:

  • MyProject\Tests\bin\Debug\SQL_scriptes\GetAllEmptyRoomsAtDateRange.sql

有什么想法吗?

【问题讨论】:

    标签: c# .net dll reflection


    【解决方案1】:

    您应该将带有 sql 代码的文件添加为嵌入式资源:

    并使用以下函数从文件中获取 SQL:

    public string GetScript(string scriptName)
    {
        var assembly = Assembly.GetExecutingAssembly();
        var resourceName = "Q46868043.SQL_scripts." + scriptName;
    
        using (Stream stream = assembly.GetManifestResourceStream(resourceName))
        using (StreamReader reader = new StreamReader(stream))
        {
            return reader.ReadToEnd();
        }
    }
    

    【讨论】:

      【解决方案2】:

      路径是相对的,但您遇到的更大问题是您的文件很可能在编译时没有被复制。

      在 Visual Studio 中转到文件的属性,并将“复制到输出目录”设置为“始终复制”或“如果较新则复制”。

      请记住,这并不意味着文件实际上嵌入到程序集中。有人可以更改文本文件,这将更改脚本。这有好有坏。

      如果您希望将 SQL 内置到实际的 DLL 中,这是一个不同的过程,您需要考虑涉及 embedded resources.

      【讨论】:

        【解决方案3】:

        您将程序集结构与文件系统中的文件夹布局混淆了。这是完全不同的事情。程序集(dll 或 exe)格式在 CLI 规范中定义,具有 PE​​ 文件格式,并在源代码编译期间创建。项目中的脚本存储在文件系统中,除非它们被标记为项目中的特定操作,即资源,它们将保持原样。

        另一方面,如果您在项目属性中将它们标记为 Embedded.Resource,它们将作为可在运行时访问的托管资源存储在您的项目程序集中。但是,在您使用 .NET 时,让您的脚本在身边似乎是一种奇怪的方法。

        可能的建议是制作静态字符串或 SqlCommand 变量并将您的 SQL 查询分配给它们。在这种形式下,它们不是存储过程。

        基于托管资源的解决方案代码如下。要使其正常工作,请将其添加到项目根文件 MySqlScripts.sql 并将其标记为 Embedded.Resource。在此实现中,默认项目根命名空间是“SqlScriptAsAResource”,这反映在嵌入资源的名称中。相应地更改文件、命名空间和嵌入式资源名称。

        using System;
        using System.IO;
        using System.Reflection;
        
        namespace SqlScriptAsAResource
        {
            class Program
            {
                static void Main(string[] args)
                {
                    Assembly myAssembly = Assembly.GetExecutingAssembly();
                    Stream resStream = myAssembly.GetManifestResourceStream("SqlScriptAsAResource.MySqlScripts.sql");
                    using(StreamReader reader = new StreamReader(resStream))
                    {
                        String sqlScript = reader.ReadToEnd();
                        // Use your SQL script
                    }
                }
            }
        }
        

        基于静态成员的解决方案是这样一个:

        using System;
        using System.Data.SqlClient;
        
        namespace SqlScriptAsAResource
        {
            internal static class SqlUtilities
            {
                public static readonly String SqlScriptValue = "SELECT * FROM Table1;";
                public static readonly SqlCommand Commadn = new SqlCommand("SELECT * FROM Table1;");
            }
        }
        

        【讨论】:

        • 你好。我看不出您的第一个选项与 kmatyaszek 的选项之间的区别。对于第二个选项,我将静态字符串用于短 SQL 脚本。
        • 您好,因此您可以证明两位编码员独立得出相同的解决方案 - 就像在科学领域,您有两篇独立的文章在同一期科学杂志的同一期中对新发现发表了相同的看法: ) 个人知道很多这样的刊物
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-23
        相关资源
        最近更新 更多