NHibernate seems to support a special case of one to one mapping (That doesn't require a 1-m mapping on each side of the relationship).
See this article by Ayende:
http://nhibernate.info/blog/2009/04/18/nhibernate-mapping-lt-one-to-one-gt.html
I have no idea how to specify this in Fluent NHibernate though - is this possible?
Ah, just found from a helpful person in the Fluent group that I can use
HasOne(x => x.Cover);
Missed it somehow before :/
One scenario is with subclasses. You can specific a table per hierarchy or per class.
You would need to override for the per hierarchy something like below:
public class UserMap : IAutoMappingOverride<User>
{
public void Override(AutoMapping<User> mapping)
{
mapping.DiscriminateSubClassesOnColumn<int>("UserType");
}
}
public void Override(AutoMapping<Person> mapping)
{
mapping.Table("Persons");
DiscriminatorValue((int)UserTypes.Person);
}
Related
Is there a clean way to mix fluent mappings with automappings? Ideally, I'd like to say "if I don't have a ClassMap for a domain object, then automap it". Is there a recommended approach? I'd rather not use attributes on my business objects that are data access related (ex: [UseAutoMapping]).
Yes - check out IAutoMappingOverride
Basically, any mappings which override the Automapping behaviour need to implement this interface.
e.g.
public class MyClassMap : IAutoMappingOverride<MyClass>
{
public void Override(AutoMapping<MyClass> mapping)
{
mapping.IgnoreProperty(host => host.HostName);
mapping.Table("BobsHardware");
}
}
I've just tried to get a project up and running with Fluent Automapping (I'm familiar with Fluent but used to write each of the maps)
I have an object ScriptType which has a ParseRules property
public class ScriptType : EntityBase
{
public virtual string Name { get; set; }
public virtual IList<ParseRule> ParseRules { get; set; }
}
This is being Auto Mapped as HasMany and I wanted References.
I therefore added an AutoMapping override to another assembly ...
public class ScriptTypeOverride : IAutoMappingOverride<ScriptType>
{
public void Override(AutoMapping<ScriptType> mapping)
{
mapping.References(x => x.ParseRules);
}
}
And altered my configuration as so ...
return configuration
.Mappings(m => m.AutoMappings
.Add(AutoMap.AssemblyOf<DatabaseInfo>()
.IgnoreBase<EntityBase>()
.Conventions.AddFromAssemblyOf<KeyConvention>()
.UseOverridesFromAssemblyOf<ScriptTypeOverride>()));
But I get this .... :(
An association from the table ScriptType refers to an unmapped class: System.Collections.Generic.IList`1[[GIT.ScriptWizard.Entities.ParseRule ...
Can anyone help please?
References is for creating many-to-one
relationships between two entities,
and is applied on the "many side."
You're referencing a single other
entity, so you use the References
method. HasMany is the "other side" of
the References relationship, and gets
applied on the "one side."
From Fluent's website.
How should your relation work? It looks like a classic one ScriptType-to-many ParseRules, so this should be HasMany on ScriptType's side, as Fluent does.
Maybe, if you want to have bidirectional relationship here, where ParseRule's side is the "owning" side of the relation, you should use Inverse() in ScriptType.ParseRules mapping override.
I have a convention for my ids, which automatically maps properties with a name of Id as the identifier. As requirements are being fleshed out I need to tweak a domain model so naturally I went online and found that I need to create a class that inherits from IAutoMappingOverride<T>.
My convention:
public class PrimaryKeyConvention : IIdConvention, IIdConventionAcceptance
{
public void Apply(IIdentityInstance instance)
{
instance.Column("Id");
instance.GeneratedBy.SeqHiLo(instance.Name, "10");
}
public void Accept(IAcceptanceCriteria<IIdentityInspector> criteria)
{
criteria.Expect(x => x.Generator, Is.Not.Set);
}
}
My override:
public class LocateMappingOverride : IAutoMappingOverride<Locate>
{
public void Override(AutoMapping<Locate> mapping)
{
mapping.Map(x => x.SendTo).Not.Nullable();
}
}
The convention does work as expected if I remove my override.
The exception I get is The entity 'LocateMappingOverride' doesn't have an Id mapped. Use the Id method to map your identity property. For example: Id(x => x.Id)..
Is it possible to use conventions in conjunction with mapping overrides?
The answer is - yes, automapping can work with overrides.
Look what the error said. The problem is not with Locate entity, but with LocateMappingOverride entity, and that class should not be treated as entity, of course. You must have IAutomappingConfiguration configured so that FluentNHibernate's rule what to treat as entity includes LocateMappingOverride, too. And it does not have an Id mapped, indeed.
You should either:
change your IAutomappingConfiguration so that classes that implements IAutoMappingOverride<> are excluded
move the override outside the scope that is searched for entities
or introduce a common marker interface that all entities need to implement, i.e. IEntity and change IAutomappingConfiguration rules respectively.
I've found a number of posts about this but none seem to help me directly. Also there seems to be confusion about solutions working or not working during different stages of FluentNHibernate's development.
I have the following classes:
public class MappedClass
{
...
}
public enum MyEnum
{
One,
Two
}
public class Foo
{
...
public virtual IDictionary<MappedClass, MyEnum> Values { get; set; }
}
My questions are:
Will I need a separate (third) table of MyEnum?
How can I map the MyEnum type? Should I?
What should Foo's mapping look like?
I've tried mapping HasMany(x => x.Values).AsMap("MappedClass")...
This results in: NHibernate.MappingException : Association references unmapped class: MyEnum
It looks like this questions is a duplicate of Fluent code for mapping an IDictionary<SomeEntity, int>?. The solution was to use hbm.xml to map a ternary association table. It looks like at the time FluentNHibernate's AsTernaryAssocation() method only worked for entity types. I can't tell if this has changed, or if it is a planned feature.
In my database every table belongs to a schema (Person for example.) I am using Fluent NHibernate with Automapping and my question is how I set the schema I want to use.
Use a convention, specifically an IClassConvention.
public class SchemaConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Schema("schemaNameGoesHere");
}
}