为什么在 DAL 中使用 Microsoft Sql Server 管理对象 (SMO) 需要在引用 DAL 的项目中引用 SMO dll?

发布于 2024-12-29 04:08:27 字数 2230 浏览 1 评论 0原文

我在谷歌上搜索了答案,使用:

“类型'Microsoft.SqlServer.Management.Smo.Server'是在未引用的程序集中定义的。”

为什么在 DAL 中使用 Microsoft Sql Server 管理对象 (SMO) 需要引用引用项目中的 SMO dll?

在引用的项目中使用 sql smo

在分层解决方案中使用 sql smo

sql smo 参考要求

以及可能的其他一些要求,但尚未找到此问题的解决方案或解释。

诚然,我只是一个熟练的谷歌搜索者,所以如果有人希望给我力量并指出现有资源的方向,我会很乐意从那里开始探索。

这是我的设置:

我有一个分层解决方案:DAL、业务逻辑、服务、UI。有一个托管服务的主机项目。我实际上使用 VS2010 扩展 layerguidance.codeplex.com 来设置所有这些项目,这非常好。我使用的是 SQL Server 2008 Express 和 SMO v 10。所有解决方案项目均使用项目引用进行引用。所有项目都编译到一个公共的顶级 Bin 文件夹中。

现在的问题是:

在 DAL 中的类中,我有一个 SmoTasks 类,它处理与 SMO 对象的接口,还有一个 Utilities 类,它从 < code>SmoTasks 并提供对其功能的访问,而不需要任何 SMO 对象作为参数,以便引用项目(读取:业务逻辑层)可以使用非 SMO 类型进行接口。 DAL 中的一切都很好,编译得很好,方法通过了测试 - 它在我的世界中的地位感觉很好。然后,在 BLL 中,我有一个组件,它使用 Utilities 类来处理将通过服务公开的应用程序的数据库配置。 BLL 使用对 DAL 的项目引用,并按预期查看 DAL 类(按照智能感知)。当我编译时,我得到:

类型“Microsoft.SqlServer.Management.Smo.Server”是在未引用的程序集中定义的。您必须添加对程序集“Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91”的引用。

BLL 中的代码如下所示:

 public bool CreateTables(string connectionString)
    {

        bool result = default(bool);


        // Data access component declarations.
        Utilities utilities = new Utilities();

        // Step 1 - Calling CreateTables on Utilities.
        result = utilities.CreateTables(connectionString);

        return result;

    }

错误指向的行是:

result = utilities.CreateTables(connectionString);

I显然,可以将 SMO 引用添加到 BLL,然后 BLL 会很高兴,但这违反了我松散耦合项目的设计目标。如果我将 SMO 程序集添加到 BLL,它会进行编译,然后在服务层中引用 BLL 对象不会引起投诉。我的问题是,为什么?更具体地说:当 DAL 中的 Utilities 类已经抽象出 SMO 类型时,为什么 BLL 需要引用 SMO?

我想要的是与存在于数据库中的所有数据库相关的内容。 DAL(废话)和 BLL 中只有业务逻辑(双废话)。 是否有另一种方法可以使用我忽略的 SMO 来实现此目的?

感谢您的宝贵时间和回答,我谦虚地等待您的回复

编辑: 我根据 Chris 的建议调整了我的解决方案,验证了我正在使用项目引用(我是),在我手动浏览和添加之前,使用 Muse.VSExtensions 在 DAL 中读取了对 SMO 的引用以添加 GAC 引用,然后我继续为这些程序集设置 Copy Local = True,只是为了双重确保它们存在......但我仍然遇到这个恼人的编译错误。

I've searched for an answer on google using:

"The type 'Microsoft.SqlServer.Management.Smo.Server' is defined in an assembly that is not referenced."

Why does using Microsoft Sql Server Management Objects (SMO) in the DAL require references to SMO dlls in a referenced project?

using sql smo in referenced projects

sql smo in layered solutions

sql smo reference requirements

and probably a few others and have not found a solution or explanation to this issue.

Admittedly, I'm only a journeyman googler, so if someone wishes to power level me and point the way to an existing resource, I'll gladly go spelunking from there.

Here's my set up:

I've got a layered solution: DAL, Business Logic, Services, UI. There's a hosts project that hosts the services. I'm actually using the VS2010 extension layerguidance.codeplex.com, which is quite nice, to set up all these projects. I'm using SQL Server 2008 Express and SMO v 10. All solution projects are referenced using Project References. All projects compile to a common top level Bin folder.

Now the problem:

Among the classes in the DAL I have an SmoTasks class which handles interfacing with SMO objects and a Utilities class which abstracts from SmoTasks and provides acces to its functions without requiring any SMO objects for parameters, so that referencing projects (read: Business Logic Layer) can interface using non-SMO types. All is well in the DAL, it compiles fine, the methods pass their tests - it feels good about its place in my world. Then in the BLL I have a component which handles using the Utilities class to perform database configuration for the application which will be exposed via the services. The BLL uses a project reference to the DAL and sees the DAL classes (a la intellisense) as expected. When I compile though, I get:

The type 'Microsoft.SqlServer.Management.Smo.Server' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91'.

The code in BLL looks like this:

 public bool CreateTables(string connectionString)
    {

        bool result = default(bool);


        // Data access component declarations.
        Utilities utilities = new Utilities();

        // Step 1 - Calling CreateTables on Utilities.
        result = utilities.CreateTables(connectionString);

        return result;

    }

The line the error points to is:

result = utilities.CreateTables(connectionString);

I could, obviously, add the SMO references to the BLL and then the BLL would be happy, but that violates my design goal of loosely coupled projects. If I add the SMO assemblies to the BLL, it compiles and then referencing BLL objects in the services layer doesn't cause a complaint. My question is, why? More specifically: Why does the BLL need references to SMO when the Utilities class in the DAL already abstracts away the SMO types?

What I want is everything database related to live in the DAL (duh) and only business logic in the BLL (double duh). Is there another way to achieve this using SMO that I have overlooked?

Thank you for your valuable time and answers, I humbly await your responses

Edit:
I've adjusted my solution based on suggestions by Chris, verified that I'm using project refs (I am), readded the references to SMO in the DAL using Muse.VSExtensions to add GAC reference, before I had been browsing and adding manually, then I went ahead and set Copy Local = True for those assemblies just to be doubly sure they're around... but I'm still stuck with this annoying compile error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

刘备忘录 2025-01-05 04:08:27

我认为这可以归结为解决方案中如何引用事物。所以我要进行一些猜测。

听起来您的 DLL 将 DAL 作为程序集引用,而不是作为项目引用。

在编译时,Visual Studio 会将其认为必需的所有内容复制到项目 BIN 目录中。如果您引用外部 DLL (DAL),那么它只会将该 DLL 复制到 BLL 的 BIN 目录。

您需要做的是让它复制 SMO 程序集,或者通过 GAC 提供这些 SMO 程序集。就我个人而言,我不喜欢 GAC 处理的事情,所以我会忽略它。

有三种方法可以做到这一点。最简单的方法是简单地将对这些其他程序集的引用添加到 BLL 中。显然这不是你想要的。

第二种方法是将 DAL 项目作为项目引用进行引用。这将允许 Visual Studio 检测额外的依赖项并相应地复制它们。这也不完全是您想要的。

第三种方法是将它们作为构建步骤的一部分进行复制。右键单击您的 BLL 项目并转到“构建事件”。在预构建事件命令行中输入命令,将必要的 SMO 文件复制到 BLL 项目 BIN 目录。

您还必须对主要服务项目再次执行此操作。

I think this boils down to how things are referenced in your solution. So I'm going to take a couple guesses.

It sounds like your DLL references the DAL as an assembly instead of as a project reference.

During compile time Visual Studio copies everything it thinks is necessary to the projects BIN directory. If you reference an external DLL (DAL) then it will copy that DLL only to your BLL's BIN directory.

What you need to do is get it to copy the SMO assemblies as well OR have those SMO assemblies available through the GAC. Personally, I don't like GAC'ing things, so I'll ignore that.

There are three ways of doing this. The easiest is to simply add a reference to those other assemblies to your BLL. Obviously that's not what you want.

The second way is to reference the DAL project as a project reference. This will allow Visual Studio to detect the extra dependencies and copy them accordingly. This is also not exactly what you want as well.

The third way is to copy them as part of a build step. Right click on your BLL project and go to Build Events. In the Pre-build event command line put in the commands to copy the necessary SMO files to your BLL projects BIN directory.

You'll have to do this again for the main service project as well.

驱逐舰岛风号 2025-01-05 04:08:27

带着歉意回答自己的问题是令人沮丧的,“我是个白痴”……但是,好吧,我是个白痴:

Utilities中,有问题的方法有一个重载, 是否包含Smo.Server参数。我删除了该过载(重构前测试中的一个工件),瞧,问题解决了/白痴得到了证实!我在这里学到的有趣的事情是,使用 Utilities 类的其他方法(没有包含 Smo 对象的重载)绝对没问题,这意味着即使使用 Utilities 中的函数也是如此。 code> 类需要一个 Smo 对象作为参数,只要我没有调用该方法或其重载之一,引用就会完美地解析。我的新问题是,为什么?如果我从依赖链较高的项目中调用该函数的另一个版本,为什么该重载的存在对于引用解析很重要?是否存在一些内部循环,它会遍历函数的所有版本,检查引用是否已调用任何版本...

It's depressing to answer your own question with a mea culpa, "I'm an idiot"... but, well, I'm an idiot:

In Utilities there was an overload for the offending method which did contain an Smo.Server parameter. I removed that overload (an artifact from testing before refactoring) and voila, problem solved/idiocy confirmed! The interesting thing I learned here is that using the other methods of the Utilities class, which did not have overloads containing Smo objects, was absolutely fine, meaning even with a function in the Utilities class which required an Smo object for a parameter, as long as I didn't call that method or one of its overloads, the references resolved perfectly without a hitch. The new question I have, is why? Why does that overload's existence matter for reference resolution if I call another version of that function from a project higher in the dependency chain? Is there some internal loop where it goes over all versions of a function checking references if any version has been called...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文