Is there any way to reuse NHibernate components (<component>) in more than one mapping?
For example: an Address class in Employee and Customer classes - The only way to do this which I see now is to copy-paste the Address component mapping from one of the class mappings into another.
I haven't tried this with NHibernate but it worked with another OR Mapper that used XML configuration files. Create the component mapping in it's own XML file, then in the XML file that uses the component use an XML external entity to reference it. Here's a snippet from my Company mapping file:
<!DOCTYPE mappings [
<!ENTITY Address SYSTEM "MyCompany.MyApplication.Mappings.Address.xml">
]>
<mappings version="4.2" defaultNamespace="MyCompany.Model" defaultSchema="dbo">
<entity type="Company" table="Company" keyMember="CompanyId" keyType="Auto">
&Address;
Apart from the solution that Jamie proposed, using code-based mappings provides better possibilities for reuse.
Currently, there are two such projects, Fluent NHibernate and ConfORM.
Unfortunally not. I really need that feature too ;)
Related
I wanted to mix class based JPA configuration with using annotations together with xml based configuration and it works fine in terms of Dynamic Fields Extensions - I can add to xml fields that are not defined in class and they are being used fine.
The question is how to do that with mappings - I wanted to add OneToOne or OneToMany mapping to the xml and have that working but no luck at the moment. Is that even possible to add for existing class new mapping to new class, in xml orm file?
I'm working on a dynamic application with NHibernate. My goal is to create dynamic entities (both class type and mapping xml file) based on some data. For example suppose I want to create a Person entity dynamically in runtime and on the fly.
I use Reflection.Emit to generate class type dynamically. For creating mapping dynamically I used Ayende's code.. But unfortunately this code does not work because mappings does not have Classes property. I tried to code as same as codes of Castle ActiveRecord and Fluent NHibernate but they generate HBM XML files. As I don't want to generate/create mapping files so I can not use these solutions.
Is there any way that like Ayende's solution not to be forced to generate HBM XML mapping files and just doing everything dynamically and in memory?
fluentnhibernate creates hbm in memory just to feed them to nhibernate. fluentnhibernate has the nice automapping feature with costumizable conventions, perfect for this situation. Also in FNH 2.0 they are working to skip hbm for better performance, but normally you'll never see the mappings outside memory.
Sample:
Assembly assembly = GetDynamicallyCreatedTypesAssembly();
ISessionFactory sf = Fluently.Configure()
.Database(...)
.Mappings(m => m.AutoMappings.Add(AutoMap.Assembly(assembly)))
.BuildSessionFactory();
NHibernate 3.2 has a mapping-by-code layer that does what you want.
I'm not sure if dynamic classes will work, but it doesn't hurt to try.
Is there any way to get references to the mapping objects that NHibernate creates from the XML files? How about the ClassMap objects that FluentNhibernate creates? I wanted to create some query generation functions (for row counts, etc.) using this information. Since I went through the trouble of mapping it, I ought to have access to it in code, right?
Actually, Fluent ClassMaps are translated to XML.
The ISessionFactory exposes a GetAllClassMetadata method that is probably what you need.
You can specify the namespace and assembly to use types from at the top of HBM files:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyCorp.MyAssembly" namespace="MyCorp.MyAssembly.MyNamespace">
Can you use types from multiple assemblies / namespaces within the same mapping file, and if so what is the syntax for doing so?
You can remove the default assembly and namespace definitions from the top of the HBM file and then specify the fully qualified type names each time they occur in the mapping file as follows:
Namespace.TypeName,Assembly.Name
Not pretty, but it works.
As Ben said, you can use qualified type names.
However, the usual practice in NHibernate is to put the mapping for each class in a separate file, which makes it easier to maintain.
Personally, I sometimes group related classes in the same file, but that's it (like XYHeader and XYDetail).
For types coming from different assemblies (which usually imply different subdomains), I even use separate projects.
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.