Fluent NHibernate 解决方案结构 - 如何在 Web 应用程序/控制台应用程序后端引用 DLL 一次
我正在使用 Fluent NHibernate 组织 VisualStudio 2008 解决方案,我希望将所有 NHibernate dll 依赖项隐藏在“后端”类库中,并让前端 Web 应用程序或控制台应用程序不了解 NHibernate。
我的解决方案结构如下:
后端 -- 类库 -- 业务逻辑和数据存储库& public API..该级别私有地使用NHibernate进行数据存储,不向前端暴露任何NHibernate类
Public -- 类库 --- 前端和后端都使用的没有依赖关系的 POCO 对象结尾。后端使用 NHibernate 来持久化这些对象。
前端——控制台应用程序和MVC Web 应用程序 --(两个前端应用程序 (1) MVC2 Web 应用程序 && (2) 控制台应用程序)引用 Public &后端项目,只需使用一些公共方法即可使用公共对象与后端进行交互。
我想做的只是在后端引用 NHibernate 及其许多依赖项,并让前端应用程序仅引用后端项目。然而,如果除了在后端引用 Nhibernate 的依赖项之外,我不在前端应用程序中引用它们,那么 Fluent 后端会在运行时崩溃。这是后端代码,当前端省略引用时,它抱怨找不到 nhibernate dll,从而崩溃:
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(SQLiteConfiguration.Standard.UsingFile(DbFile))
.Mappings(m => m.AutoMappings
.Add(AutoMap.AssemblyOf<EngineInfo>(type => type.Namespace.Contains("BackEnd"))
.Conventions.Add(DefaultCascade.All())
.Conventions.Add(DefaultLazy.Never())
)
) //emd mappings
.ExposeConfiguration(BuildSchema)//Delete and remake a fresh tmp db
.BuildSessionFactory();//finalizes the whole thing to send back.
}
可能是我不小心向前端应用程序公开了 NHibernate 依赖资源,但我没有得到任何信息编译时错误,我希望得到一点指导。
如果我确实引用 Nhibernate 的 dll,一切都运行良好,但在我的前端应用程序中,我在编译时收到以下警告:
*
发现不同之间存在冲突 相同依赖项的版本 组装。
*
有什么建议吗?
--更新--
我已经将前端必须引用的 dll 缩小到 NHibernate.ByteCode.Castle.dll 和 系统.数据.SQLite 我可以跳过所有其他错误并且不会出现运行时错误..至少还没有。
我仍然不确定为什么需要其中任何一个,因为前端从不使用任何 NH 或 SQL lite 资源,除非通过后端的公共接口,而后端不提供任何 Nhibernate 或 SQLite 资源。所有涉及 NHibernate 或 SQLite 的类都被标记为“Internal”,所以我不确定什么会导致这种依赖性。
Visual Studio 依赖项警告提供了一个解决方案,我有点犹豫是否要应用它,因为我不知道为什么会首先出现问题:
您想通过向 appconfig 文件添加绑定重定向记录来解决这些冲突吗? --- MSDN 关于该选项 -- http://msdn.microsoft.com /en-us/library/bb383993.aspx
有什么建议吗?
---更新--- 下面的 Tom 似乎复制了我的问题,因此这听起来像是 NHibernate dll 错误。我还尝试从 VS 2008 升级到 2010 并重建整个解决方案并在那里复制错误。在我尝试报告之前,有人想看一下以确保我们没有遗漏任何内容吗?
I'm organizing a VisualStudio 2008 solution using Fluent NHibernate and I would like to keep all the NHibernate dll dependencies buried in a "Back End" class library and let the front end Web app or Console app be ignorant of NHibernate.
My Solution structure is as follows:
BackEnd -- Class Library -- Business logic and Data Repositories & public API.. this level uses NHibernate privately for data storage and does not expose any NHibernate classes to the front end
Public -- Class Library --- POCO Objects with no dependencies used by both front end and back end. Backend uses NHibernate to persist these objects.
Front End -- Console App & a MVC Web App -- (Two front end apps (1) MVC2 Web app && (2) a console app) reference the Public & Back End projects and just use a few public methods on to interact with the Back End using Public objects.
What I would like to do is only reference NHibernate and its many dependencies once in Back End and have the Front End apps just reference the back end project. However, the Fluent BackEnd crashes at runtime if I don't reference every one of Nhibernate's dependencies in my front end app in addition to referencing them in the Back End. Here's the Back End code it crashes on complaining it can't find the nhibernate dlls when the front end omits the reference:
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(SQLiteConfiguration.Standard.UsingFile(DbFile))
.Mappings(m => m.AutoMappings
.Add(AutoMap.AssemblyOf<EngineInfo>(type => type.Namespace.Contains("BackEnd"))
.Conventions.Add(DefaultCascade.All())
.Conventions.Add(DefaultLazy.Never())
)
) //emd mappings
.ExposeConfiguration(BuildSchema)//Delete and remake a fresh tmp db
.BuildSessionFactory();//finalizes the whole thing to send back.
}
It may be that I've accidentally exposed a NHibernate dependent resource to the Front End apps but I don't get any compile time errors, and I'd love a little direction.
If I do reference Nhibernate's dlls everything runs fine but in my front end apps I get the following warning at compile time:
*
Found conflicts between different
versions of the same dependent
assembly.
*
Any suggestions?
--Update--
I've narrowed the dlls that I have to reference in the front end down to
NHibernate.ByteCode.Castle.dll and
System.Data.SQLite
I can skip all the others and not get runtime errors.. at least none yet.
I'm still not sure why either would be required because the front end never uses any NH or SQL lite resources except through the public interface of the back end which doesn't offer any Nhibernate or SQLite resources. All classes that touch NHibernate or SQLite are marked Internal so I'm not sure what could cause this dependency.
The visual studio dependency warning offers a solution that I'm a bit hesitant to apply since I don't know why the problem came up in the first place:
Do you want to fix these conflicts by adding binding redirect records to the appconfig file? --- MSDN on the option -- http://msdn.microsoft.com/en-us/library/bb383993.aspx
Any advice?
---Update---
Tom below seems to have replicated my problem so this is starting to sound like a NHibernate dll bug. I also tried upgrading from VS 2008 to 2010 and rebuilt the whole solution and replicated the error there. Any one want to take a look to make sure we're not missing something before I try to report it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我正在开发一个具有类似架构的项目,昨天就遇到了类似的问题 - 需要在我的项目中包含对 NHibernate 的引用,即使代码中没有对这些程序集的直接引用。
否则,会出现运行时错误,抱怨无法找到 NHibernate.ByteCode.Castle。
问题原来出在我的构建方式上。 NHibernate 程序集没有正确传播到我的应用程序的运行时目录,因为我使用的是标准 VS2008 文件夹结构(bin\Debug 等)。
修复的第一部分是创建一个目录,在其中构建和运行所有程序集。您可以通过将解决方案中所有项目的输出路径(在项目的“生成”选项卡上)设置为指向此目录来完成此操作。
修复的第二部分是为所有 NHIbernate 引用以及解决方案中的其他程序集设置 Copy Local = True(您不需要为标准程序集 - 系统等设置此设置)。这会导致 VS 在每次构建时将项目使用的所有程序集复制到公共运行时目录。
然后,您应该能够从所有不直接使用 NHibernate 的项目中消除它们的引用。
这对我有用,但我不禁想知道是否有更好的方法来解决这个问题。但现在就这样了。
编辑:
经过更多测试,似乎所有 Castle DLL 都存在问题,其中 NHibernate.ByteCode.Castle 最明显。
我的应用程序中的项目之一是一个包含 NHibernate 逻辑的程序集,其中包含对所有 NHibernate DLL 的引用,包括 NHibernate.ByteCode.Castle。
当我在另一个项目中添加对该程序集的引用并构建它时,所有 NHibernate DLL 都会被复制到另一个项目的输出目录 - 除了 Castle DLL!。
其他人也遇到过类似的问题我尝试了一些建议的解决方法,没有运气。
我强烈怀疑 Castle DLL 不能正确支持 Microsoft 将依赖程序集传播到其他项目的约定,但还不够确定。
I'm working on a project with a similar architecture, and ran into similar problems just yesterday - needed to include references for NHibernate in my project, even though there no direct references in the code to those assemblies.
Otherwise, got a runtime error, complaining about not being able to find NHibernate.ByteCode.Castle.
The problem turned out to be the way I was building. The NHibernate assemblies were not being properly propogated to my application's runtime directory, because I was using the standard VS2008 folder structure (bin\Debug, etc).
The first part of the fix was to create a single directory where all the assemblies are built and run. You can do this by setting the Output path (on the project's Build tab) for all the projects in your solution to point to this directory.
The second part of the fix was to set Copy Local = True for all the NHIbernate refs, and also the other assemblies in your solution (you don't need to set this for the standard assemblies - System, etc). This causes VS to copy all the assemblies used by a project to the common runtime directory everytime you build.
You should then be able to eliminate the NHibernate references from all the projects that don't use them directly.
This worked for me, but I can't help wondering if there's a better way to solve this problem. But it will do for now.
Edit:
After some more testing, it appears that there is a problem with all the Castle DLLs, NHibernate.ByteCode.Castle most notably.
One of the project's in my application is an assembly that contains the NHibernate logic, which contains references to all the NHibernate DLLs, including NHibernate.ByteCode.Castle.
When I add a reference to that assembly in another project, and build it, all the NHibernate DLLs get copied to the other project's Output directory - except the Castle DLLs!.
Other people have had similar problems I tried some of the workarounds suggested, with no luck.
I strongly suspect that the Castle DLLs don't properly support Microsoft's conventions for propagating dependant assemblies to other projects, but don't know enough to be sure.
一些 NHibernate 相关的 dll 可能在 Web 项目中引用,而不是在后端项目中引用。如果你真的找不到它,请删除所有 NHibernate 相关的 dll,清理你的解决方案并将它们添加到后端项目中。
Some of the NHibernate related dlls are probably referenced in the web project instead of the backend project. I you really can't find it, remove all NHibernate related dlls, clean your solution and just add them to the backend project.
我解决了这个问题。在我的 DataAccess 项目(NHibernate 和 NHibernate.ByteCode.Castle 引用所在)中,我创建了这个简单的类:
我从不使用这个类(显然),但它的存在只是帮助 NHibernate.ByteCode.Castle.dll (和 Castle.Core.dll )出现在引用项目的 bin/ 目录中。
在解决方案结构中,我有单独的目录,其中放置了所有相关的 dll(NHibernate、Castle、Fluent 等),因此这里没有 GAC。
I worked this issue around. In my DataAccess project (where NHibernate and NHibernate.ByteCode.Castle references are) I created this simple class:
I never use this class (obviously), but it's only existence helped NHibernate.ByteCode.Castle.dll (and Castle.Core.dll) to appear in referencing project's bin/ directory.
In the solution structure I have separate directory where I placed all related dlls (NHibernate, Castle, Fluent, etc.), so no GAC here.
您需要急切地加载或 NHibernateUtils.Initialize 您的对象,然后再通过网络发送它们,我怀疑是城堡代理包装器给您带来了悲伤。
You need to eager load or NHibernateUtils.Initialize your objects before sending them over the wire, it is the castle proxy wrapper that is giving you grief I suspect.