I'm currently designing solution where the domain model & the repository can be extended by application plugins. Now, i have come across a few issues that i am listing below.
My first issue is making domain model extensible. I was thinking about using inheritance here, but honestly, i have no idea how i can leverage multiple plugin assemblies extending the same domain object. I'm kind of leaning toward making every domain object partial and allowing plugins extend it this way. In case i have multiple plugins extending the same domain object, i won't have to worry about loading different extended domain assemblies for each plugin. I would still have only one merged domain object at run-time. Any ideas on this?
Another issue is extending the NHibernate mapping file. I could have each assembly embed mapping file for the domain object it's extending and have my NHibernate manager load it instead of the one provided in the core domain. Once again, the issue is what if i have multiple plugins extending the same domain object. I could have one plugin overriding mapping file for the other.
The solution i have to the last problem is not so great, but I was thinking about including a checksum into the plugin assembly as a signature for the original mapping file it used before extending it. I can verify this checksum during load and only load the plugin map if the checksums match. Pretty ugly, but at least i won't be overriding any maps that differ from the base map used to extend upon in the plugin assembly.
Any way, i'd like to hear what you guys think about this. Thanks!
The good news is that what you are asking for is possible and not that difficult to manage.
About plugin management, you can take a look at Microsoft Prism (http://msdn.microsoft.com/fr-fr/magazine/cc785479.aspx) which as several nice features about modular application development.
About 1. You can map subclasses in separate mappings, in separate assemblies, look for NH documentation. A separate mapping file for a subclass looks like this :
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<subclass name="YourClassFullName, YourPluginAssemblyName"
extends="YourParentClassFullName, TheAssemblyWhereYourBaseClassIsDefined"
discriminator-value="whateveryouwant">
... add your subclass mapping here ...
</subclass>
</hibernate-mapping>
About 2. You can keep your core domain mapping. A simpler way would be to create a service (let's say IMappingLoader) your plugins can use to register your extra mappings (without overriding the base class mapping). Your implementation of this service would add your mapping to NH Configuration class. For example, in Microsoft Prism, all your plugins must implement the IModule interface, which function Initialize() is called when it is loaded. This function is the ideal place to call your IMappingLoader service.
Hope it helped.
To get domain model extensible I'll use lots of factories. Factories can be swap in/out via dependency injection and domain objects should be coded against interfaces.
Mapping could be done for instance via Fluent NHibernate and these could be in that plugin assembly.
Finally I would add loadable configuration to that plugin assembly, which setups DI container and load new mappings. For main assembly there could be scanner for plugin configurations. Maybe MEF could be helpful here or you could make your own, which should not be complicated.
Related
I am new to EclipseLink. I am trying to generate orm mappings for a class during runtime and do mapping.
Is it possible at all?
I see examples where a class is generated during runtime but that doesn't fit my situation.
thanks
It could be possible, depending on what you are trying to do and when. Persistence units are pretty static creations that should be known upfront - just like java classes themselves. So if you are not using Dynamic entities, why wouldn't you know upfront that the class should be apart of the persistence unit up front?
While it is not a great idea, you could create a static persistence unit and specify that it use a customizer as described here http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Customizers with which you could add in descriptors or mappings to the persistence unit. The customizer is only run once though, during initialization. So if you wanted to make changes later on, you would need to refresh the persistence unit using the refreshMetadata on the EntityManagerFactory to have it reload the persistence unit. Running EntityManagers will not be affected by the changes.
Using the EMF refreshMetadata, you could also use a MetadataRepository to pick up different or extended ORM.xml files for your entities - so you could incorporate changes made to the xml instead of using a customizer. This is described somewhat here:
http://www.eclipse.org/eclipselink/documentation/2.5/solutions/extensible001.htm#CIAIJHAG
Well, I am creating a WCF service, that have a large number of classes to communicate with the client, and this classes have also many properties.
Mainly, this classes are the POCO classes that is created with the code generator from the edmx, and I have the .tt file.
To can use this classes and properties, I have to use the DataContract and DataMember, so in each classes I have to set the DataContract and in each property of the each class the DataMemeber. So this a big work, so if I need to do some modify to the data base, I must generate again the tt file and then repeat the work.
Is there any way to do this automatically? I am using .NET 4.0 and EF 4.1.
The whole point of the .tt file being added to your project is so that you can modify the template to suit your needs. All you need to do is change the template so that it adds [DataContract] to the entity class definition and [DataMember] to the entity property definitions.
From there, any time the DB is changed you simple use the "Update model from database" feature and your entities will automatically have their code regenerated using the existing template.
All that said, I'm going to recommend you do not expose your DB entities, POCO or not, directly from your service layer. You should really be designing with domain separation and using messaging and CQRS type patterns at the service level. Then you just have some simple mapping methods that translate the data between those messages/commands to your entities.
There is Entity Framework Provider with WCF data services, might be it can help you.
Now that I have a good handle on NHibernate 3.2 I now feel ready to use it in anger. What I need now is an ellegant way to inject the mappings I want from an IoC container like castle windsor or the like.
The project that I am working on requires 2 sets of mappings, one to a legacy database that needs to stay put for now and one to the new schema designed to replace the old database at some point in the future. Baring in mind that I am using mapping by code rather than xml mapping.
So at a controller/middle tier level you'd be injecting a repository that implements your ISomethingRepository interface and as a parameter into that repository somehow passing a collection of ClassMapping objects.
Any ideas about the best way to go about this would be appreciated. I'm interested in the general architecture which is why I'm not specifying an IoC container.
Why not have a SessionFactoryFactory which consumes a ConfigurationGenerator.
Due do LinqToSql not being appropriate for Many To Many relationships I am in the process of deciding to move to NHibernate (Fluent NHibernate) unless convinced otherwise...
Project Structure: UI (Mvc2 app with Ninject wiring up all services to controllers, and repositories to services), DomainServiceLayer (all util, helpers, services, domain model etc) and my Repository Layer for persistence. I have a another project call Model which basically exposes the entities, which all projects reference.
Basically I am creating my mappings within the Repository Layer with references to NHIbernate and Fluent NHIibernate, I hope to expose the interfaces to the Domain Service for querying and persisting data. How do I wire up the iSession, where do I wire it up? Any example code, what project should I put it in? Ideally I want to keep this within the Repository Layer... Is it worth learning NHibernate and going through all this?
I recommend looking at the blog posts of Bob. He describes in detail how to use the repository pattern in Ninject using NHibernate. I planned adding an example in the near future to the sample application comming with the MVC exptension as this question comes up again and again.
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/
Typically I have an NHibernateSessionFactory which is a singleton that has an OpenSession method and I bind ISession typically like this.
Bind<ISession>().ToMethod(context =>
NHibernateSessionFactory.Instance.OpenSession()).InRequestScope();
This method just calls through to ISessionFactory.OpenSession
You can put this into a NinjectModule in your repository layer, which your app can load when it creates the Kernel.
I do the configuration in the Application Layer (i.e. the top layer) as the configuration differs between applications. But it can be useful to break out some of the configuration into classes stored in the Repository Layer.
I open and close the session with an HttpModule.
I try to set-up a clean and flexbible application-framework for data-centric applications with silverlight-only UI. I want to have a strict seperation of concerns, and want to be as flexible as possible (e.g. exchange the ORM later) while still reducing the amount of code.
It took me weeks to figure out an appropriate architecture, and although my latest approach seems to fit my requirements I'm still not completely convinced, that this way will be the best and is technically possible.
Here is how my solutions-explorer looks like:
MyCompany.MyApplication.Entities
Class library - project, which contains only the domain (business) objects, such as Customers, Adresses, etc. These are POCOs with the [Serializable] - attribute, but do not any other code. All properties are marked as virtual, so that classes could derive and overwrite the properties.
MyCompany.MyApplication.DataAccess
Class library - project, which contains the nHibernate - specific code (Sessions) to load, save and delete the domain objects. This project has references to the Entities-project and also to the nHibernate-libraries.
MyCompany.MyApplication.Core
Class library - project, which contains the business logic, and often just maps the methods form the DataAccess - project, such as GetAllCustomers, SaveCustomer, etc.
It has references to the Entities-project and the DataAccess-project.
MyCompany.MyApplication.Web
Web-application - project, which hosts the silverlight-client-app and also the WCF-services to communicate with the client-side. To expose the domain-objects to the client-side, these classes are derived and all the properties are overwritten and marked with the [DataMember] - attribute. It has references to the Entities-projects and the Core-projects.
MyCompandy.MyApplication.Silverlight
Sivlerlight 3.0 - project, which represents the userinterface. It has only service-references to the WCF-Services exposed by the Web-project. The actual domain-objects aren't accesssible, but the auto-generated proxy-classed replace them.
Please tell me, what do you think about this architecture, and if there are any conflicts! Further question: Is there any way, to avoid the properties of the domain-objects being virtual and the need to overwrite them in order to make them accessible trough WCF?
Best regards,
Daniel Lang
Daniel, you are not going to get around the nhiberante requirement of virtual properties. Have you thought about using Dto's?