开发者

Fluent NHibernate Solution Structure - How to reference DLL's once in back end of Web App / Console App

开发者 https://www.devze.com 2022-12-20 15:30 出处:网络
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 o

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()
         .Datab开发者_如何学运维ase(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?


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.


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.


I worked this issue around. In my DataAccess project (where NHibernate and NHibernate.ByteCode.Castle references are) I created this simple class:

/// <summary>
/// This class is only to fix building issue of NHibernate.ByteCode.Castle.dll 
/// not being copied to bin directory of projects referencing data access 
/// (either directly or indirectly)
/// </summary>
internal abstract class ReferenceHelper : ProxyFactory
{
}

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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消