 |
|
|
 |
|
 |
[FileNotFoundException: Impossible de charger le fichier ou l'assembly 'Business' ou une de ses dépendances. Le fichier spécifié est introuvable.]
System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +0
System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +54
System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +211
System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +141
System.Reflection.Assembly.Load(String assemblyString) +25
NHibernate.Cfg.Configuration.AddAssembly(String assemblyName) +62
[MappingException: Could not add assembly Business]
NHibernate.Cfg.Configuration.LogAndThrow(Exception exception) +62
NHibernate.Cfg.Configuration.AddAssembly(String assemblyName) +116
Shared.NHibernateDAL.NHibernateSessionManager.InitSessionFactory() in C:\Users\lotfi\Documents\Visual Studio 2008\Projects\test3\test3\NHibernateDAL\NHibernateSessionManager.cs:68
Shared.NHibernateDAL.NHibernateSessionManager..ctor() in C:\Users\lotfi\Documents\Visual Studio 2008\Projects\test3\test3\NHibernateDAL\NHibernateSessionManager.cs:40
Shared.NHibernateDAL.Nested..cctor() in C:\Users\lotfi\Documents\Visual Studio 2008\Projects\test3\test3\NHibernateDAL\NHibernateSessionManager.cs:49
[TypeInitializationException: Une exception a été levée par l'initialiseur de type pour 'Nested'.]
Shared.NHibernateDAL.NHibernateSessionManager.get_Instance() in C:\Users\lotfi\Documents\Visual Studio 2008\Projects\test3\test3\NHibernateDAL\NHibernateSessionManager.cs:31
Shared.NHibernateDAL.BusinessObject`1.Save() in C:\Users\lotfi\Documents\Visual Studio 2008\Projects\test3\test3\NHibernateDAL\BusinessObject.cs:11
_Default.Page_Load(Object sender, EventArgs e) in c:\Users\lotfi\Documents\Visual Studio 2008\Projects\test3\test3\Default.aspx.cs:20
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +33
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1436
|
|
|
|
 |
|
 |
I guys I have been using LLBLGen and LLBLGen Pro so I am new to NHibernate and Active Record.
Actually I could not get the castle projects Mono to compile so I looked here. I think they need to update it.
Can you tell me where I can get this NHibernate database from that you are using? Or do I just create one in SQL and create a product table, then what goes into it?
Regards,
Alistair
Alistair Rigney
Software Engineer
Choose the appropriate technology before you do anything and check codeproject, sourceforge if someone has done it before.
|
|
|
|
 |
|
 |
On a different note, I just found your article and wanted to let you know that I liked your solution to the nested transaction problem. Providing the commit and rollback code in the dispose keeps the code a bit cleaner what with not needing the try catch and explicit begin, commit, rollback. Good job. We also implemented a transaction stack mechanism, but it relies on a more traditional try catch block.
To address the subject of this comment though, CallContext is not necessarily a safe place to put per thread values in a web environment. I'm not sure if that's what you're doing, but I figured I would pass this on as it caused us a bunch of problems in production. The problem is that a single web request is not guaranteed to live in a single thread context. I can't do the subject of context switching justice even if I took the time, but I'll drop a couple of links below.
Our solution was to check if HttpContext.Current != null. If it exists store items in HttpContext.Items, otherwise, use the CallContext: (sorry for the VB)
<System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, _
flags:=System.Security.Permissions.SecurityPermissionFlag.Infrastructure)> _
Public NotInheritable Class ContextCache
Private Sub New()
End Sub
Public Shared Function GetData(ByVal key As String) As Object
If System.Web.HttpContext.Current IsNot Nothing Then
Return System.Web.HttpContext.Current.Items.Item(key)
Else
Return System.Runtime.Remoting.Messaging.CallContext.GetData(key)
End If
End Function
Public Shared Sub SetData(ByVal key As String, ByVal value As Object)
If System.Web.HttpContext.Current IsNot Nothing Then
If System.Web.HttpContext.Current.Items.Contains(key) Then
System.Web.HttpContext.Current.Items(key) = value
Else
System.Web.HttpContext.Current.Items.Add(key, value)
End If
Else
System.Runtime.Remoting.Messaging.CallContext.SetData(key, value)
End If
End Sub
End Class
http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html[^] Good overall description of the context switching problem.
http://msdn.microsoft.com/msdnmag/issues/05/01/ASPNETPerformance/#S6[^] Microsoft's recommendation at #5.
Hope you find this useful.
|
|
|
|
 |
|
 |
Hi,
Thank you for the info.
From what I was reading this issue was introduced in ASP.NET 2.0. The funny thing is that I've seen a lot of projects relying on CallContext.
I'll try to use your suggestion here. The downside is that it needs a reference to System.Web, which is kind of ugly for desktop apps. But it seems it's the only solution available.
Regards,
Cassio Alves
|
|
|
|
 |
|
 |
You are correct. It's not the prettiest. On the plus side, since System.Web lives in the GAC, at least the assembly is not crufting up the bin directory of your desktop applications.
The primary service that we offer currently runs with a combination of the main web site, a second web site for our web API, three services and a newly added desktop application. This approach is working well for us.
If you're worried about the footprint of your windows applications, I suppose you could base the if statement off of a config value instead of HttpContext.Current != null, or use a factory method to create a wrapper for the two different approaches. That way System.Web would not be loaded unless you really were in a web app. Avoiding the reference didn't seem all that necessary to us though.
Take care
Chuck
|
|
|
|
 |
|
 |
Hi Cassio,
Just one question: do you have a sampleProject with winforms? (I want to apply your architecture with winforms, but i'm starting whit nHibernate)
Thanks a lot!
Saludos
JC
|
|
|
|
 |
|
 |
Hi Juan Carlos,
I don't have a sample using winforms yet, but i think it should just work, since I am not using any specific ASP.NET feature, like a HTTPModule. Why don't you try it out and let me know how it goes?
Regards,
Cassio Alves
|
|
|
|
 |
|
 |
Business objects should do work based on business rules, not shovel data in and out of the database.
|
|
|
|
 |
|
 |
I personally, do not like the ActiveRecord approach to NHibernate. Because now you have created a depenedency between your business objects and nhibernate. In addition to this, All of your business classes MUST inherit from BusinessObject.
I place all of my Repository classes in a seperate assembly, and my Repository Interfaces within the core assembly. Then at runtime, Repository instances are injected into my domain layer. This eliminates the need for any nhibernate dependencies within my domain. It also eliminates the need for my business object from inheriting from a specific class.
Don't get me wrong, your method is MUCH better than plain old n-tier architecture, but I feel this method is flawed and creates tightly coupled architecture.
Now, if you want a quick and easy domain model that is persistable with NHibernate, you should check out Castle Projects' ActiveRecord project. It allows you to use attributes on your domain classes, and uses an ActiveRecord approach to the problem. This makes it much easier because you can do away with your nhibernate configuration file and let castle activerecord handle the problem instead. Here is a link to the project: The Castle Project.
Well written article though! I hope you take my comments as constructive criticism and not negatively =)
|
|
|
|
 |
|
 |
Sean, I agree with you. I too place my repository classes in a seperate library to avoid dependencies and I too use Castle's microkernel/windsor for IoC.
However, you have contradicted yourself. You said that using the base class (or other methods) creates a tightly coupled architecture with nHibernate... however, you also stated that using Castle's ActiveRecord was ok??? ActiveRecord relies on attributes that are tightly coupled with Castle.ActiveRecord, which in turn is tightly coupled with nHibernate.
|
|
|
|
 |
|
 |
I should have been more descriptive in my response.
I didn't say that using ActiveRecord was "ok", I was stating that if you DO want to use the ActiveRecord approach, then using Castle Projects ActiveRecord is a good option as it allows you to use attributes, you are correct in saying that this still tightly couples your domain model to nhibernate, just another option from your approach.
I have played with Castle's ActiveRecord but chose not to use it for the reasons that you stated. I didn't state that using Castle's ActiveRecord was better than your approach, its the same exact thing, just with a couple of other added benefits,(no nhibernate configuration file and attributes usage), but you still have the same side effects as your article.
I hope that makes my point clear. =)
|
|
|
|
 |
|
 |
I would agree with Sean's points as well. I think you're headed in the right direction, but that the tiers aren't separated enough if you're going for a data-access-agnostic domain layer. But, instead, if you're going for an Active Record[^] approach, then I would go all the way and embrace Castle Project's ActiveRecord[^] project. Furthermore, using Castle Project's ActiveRecord works hand-in-hand with Castle Project's Automated Transaction Management[^] which makes transaction management a much simpler task.
But in the context you presented, I very much liked your TransactionBlock. It seemed to make it easy to employ transactions only when needed within the specific context that it's applicable to. A drawback to my suggestions, described at http://www.codeproject.com/aspnet/NHibernateBestPractices.asp[^], is that a transaction is always applied to the entire HTTP request. To resolve it, I'm trying to create a custom transaction manager that extends from Castle Project's. We'll see how it goes.
Your article was well written and I look forward to seeing other articles from you in the future.
Billy McCafferty
|
|
|
|
 |
|
 |
Hi,
Thank you for your feedback.
Sean, I can see your point when you say that my business objects are dependent on NHibernate. Although for the projects I am implementing right now, it is not a big deal. For some kinds of projects I prefer to create a dependency on something that probably will never change, than sacrifice simplicity, productivity or even performance. Plus, the business objects don´t have any code that is specific to NHibernate, so if we decide to use DLinq(?!) next year, I probably wouldn´t have to touch the objects (probably I would need to add DLinq attributes). Anyway, that´s just my point of view.
I would be glad to see the architecture you mentioned. Do you have it published?
I will take a look at the Castle Project, altough I like the idea of xml configuration files better than hardcoded attributes.
Billy, thanks for the compliment. Your article is very nice. It was of great help.
Regards,
Cassio Alves
|
|
|
|
 |
|
 |
In my article, i left there some links regarding "TransactionGuards". LocalTranGuard - a TransactionScope Fix/Wrapper for LocalTransactions[^]
Maybe the links will help you. But the solution represented here is nice. My solution (the fix) is also similar, but it was checked also in multi-threaded enviroment (it already contains a small bugfix), so maybe it's worth checking it out.
Nice work, a WoaW to all NHibernate fans/article writers.
C#, ASPX, SQL, novice to NHibernate
|
|
|
|
 |
|
 |
Man what an excellent link of Castle Project, that is a very good help and you can also include the ActiveWriter, nice tool.
Thanks for the link.
|
|
|
|
 |
|
 |
I agree with Cassio that it depends on the project. I have used both approaches, (1) business Domain seperated from persistence layer which depends on NHibernate, and (2) ActiveRecord. I can say that ActiveRecord saves a ton of code, development time, testing etc. Of course, these savings could all be lost (and more) if you ever needed chuck NHibnerate or add some other persistence mechanism. So you need to ask yourself, based on business realities, how much am I (or my client) willing to invest now to ensure flexibility in the future? What's the likihood that this flexibility will ever be needed? And when asking this question keep in mind that a dollar today is worth a lot more than a dollar two or three years from now that might never even be spent. That said, many many cases will still indicate a more layered approach from the get go.
|
|
|
|
 |
|
 |
Thank you for the excellent intro article. I've been hoping somebody would write something like this! Hopefully my question isn't too technical for the intent of your article, but here goes--
Are Business Objects mapped 1::1 to the underlying persistent store table? Or, for example, can you have a business object that is the aggregate of several tables (think of an SQL view)? If so, how does NHibernate handle the relationships between the different tables, especially since the join types may not always be inner join? Would this require writing the SQL to "help" NHibernate in the query and subsequent updates?
Marc
Thyme In The CountryInteracxPeople are just notoriously impossible. --DavidCrow There's NO excuse for not commenting your code. -- John Simmons / outlaw programmer People who say that they will refactor their code later to make it "good" don't understand refactoring, nor the art and craft of programming. -- Josh Smith
|
|
|
|
 |
|
 |
I'm not the author of the article but I as I known (I'm not an expert...) you can't aggregate more than one table on the same business object.
I think that there are basically 4 class mapping features (that can also be combined):
1) 1::1 (the most common solution where each table is mapped to a class)
2) join associations: one-to-many, many-to-one, one-to-one (in this case you must declare an object for each table but then you can define what type of association exist between the objects). Typically used for collection mapping and parent-child relationship.
3) component (maps properties of a child object to columns of the table of a parent class). So for example you can write: Person.Address.City
4) inheritance mapping, to map a class hierarchy on the db:
-table per class hierarchy (or subclass mapping)
-table per subclass (or joined-subclass mapping)
-table per concrete class (I think not recommended)
I think that at this page you can find more informations:
NHibernate doc
especially at
NHibernate doc\Basic O/R Mapping
Davide
|
|
|
|
 |
|