Fluent NHibernate set all IDs to assigned - fluent-nhibernate

I know I can manually set each Id property to assigned using Assigned().
Is there any way of applying this globally, as I want to do it on every entity?

Sure, just register FluentNHibernate convention like this:
public class AssignedIdConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.GeneratedBy.Assigned();
}
}
Registration goes like this:
Fluently.Configure()
.Mappings(...)
.Conventions.Add<AssignedIdConvention>()

Related

IIdConvention "overrides" IAutoMapping

I'm using a specific convention for my Id tables and I'd like to override the way the ID of a specific entity is mapped. In this scenario, most of the entities should a key on the form Class+ID (ex.: EmployeeId, DepartmentId, etc), but I'd like to use a specific property for a couple of enties. So, I've added a default convention rule:
class MyPrimaryKeyConvention:IIdConvention{
public void Apply(IIdentityInstance instance) {
instance.Column(instance.EntityType.Name + "Id");
instance.GeneratedBy.Assigned();
}
}
And then, I thought I could override the mappings of the "special" EmployeeShortInfo class by doing something like this:
public class EmployeeShortInfoIdOverride: IAutoMappingOverride<Dtos.EmployeeShortInfo> {
public void Override(AutoMapping<Dtos.EmployeeShortInfo> mapping) {
mapping.Id(e => e.EmployeeId);
}
}
Unfortunately, fluent will try to use EmployeeShortInfoId instead of using the EmployeeId property. Shouldn't IAutoMappingOverride override the default convention of a class?
thanks.

Fluent nhibernate automapping collection

I am trying to map my collections with FNHib automapping. The problems that I want to solve are:
1) I want all my collections in the project to be mapped via private field. How can I say that globally?
2) Is there any way to automap bidirectional relationship without explicitly overriding each of my entities.
class OrganizationEntity example:
private ISet<> _collectionWarehouse;
public virtual IEnumerable<WarehouseEntity> CollectionWarehouse
{
get{return _collectionWarehouse; }
set{_collectionWarehouse = new HashedSet<WarehouseEntity>((ICollection<WarehouseEntity>)value)}
}
Class WarehouseEntity example:
public virtual OrganizationEntity Organization{get;set;}
You can map your collections to a private field 'globally' with the following convention:
// assumes camel case underscore field (i.e., _mySet)
public class CollectionAccessConvention : ICollectionConvention
{
public void Apply(ICollectionInstance instance) {
instance.Access.CamelCaseField(CamelCasePrefix.Underscore);
}
}
Whenever you want to set a 'global' automap preference in FNH, think conventions. The you use the IAutoOverride on a given class map if you need to.
As far has the set (a HashSet is usually what I really want also) part, the last time I had to do some mapping, I did need to do an override, like:
public class ActivityBaseMap : IAutoMappingOverride<ActivityBase>
{
public void Override(AutoMapping<ActivityBase> m)
{
...
m.HasMany(x => x.Allocations).AsSet().Inverse();
}
}
I do agree that should translate into a convention though, and maybe you can do that these days. Please post if you figure it out.
HTH,
Berryl
CODE TO USE A HASHSET as an ICollection =================
public virtual ICollection<WarehouseEntity> Wharehouses
{
get { return _warehouses ?? (_warehouses = new HashSet<WarehouseEntity>()); }
set { _warehouses = value; }
}
private ICollection<WarehouseEntity> _warehouses;

Is it possible to use a Fluent NHibernate convention to map all ICollections as sets?

Is it possible to use a Fluent NHibernate convention to map all ICollections as sets? I have an entity like so:
public class NoahsArk
{
public virtual ICollection<Animal> Animals { get; set; }
public NoahsArk()
{
Animals = new HashSet<Animal>();
}
}
With fluent mappings, this property would be mapped as HasMany(x => x.Animals).AsSet(), but how would I do this with a convention that I want to use with the automapper?
I should add that by default, ICollections get persisted as ILists, and I get a cast exception when it tries to cast the HashSet to IList.
This isn't possible in a convention, currently. If you want the automapper to treat your collections as sets by default, use ISet instead of ICollection.
In response to Christina's question, you have to create a new class that implements IAutoMappingOverride<T>:
public class AlbumOverride : IAutoMappingOverride<Album>
{
public void Override(AutoMapping<Album> mapping)
{
mapping.HasMany(x => x.Pictures).AsSet().Inverse();
}
}
Then tell FNH to use it in the configuration:
Fluently.Configure()
.Database(...)
.Mappings(m => m.AutoMappings.Add(AutoMap.Assemblies(...)
.UseOverridesFromAssemblyOf<Album>()))
.BuildConfiguration();
You'll need a new override class for every entity you need an override for, but it's mostly a copy and paste affair.

Using Fluent NHibernate Auto Mapping to map IDs of type object from base Entity class

In the project I'm working on now, we have base Entity class that looks like this:
public abstract class Entity<T> where T : Entity<T>
{
public virtual object Id { get; protected set }
// Equals, GetHashCode overrides, etc...
}
Most classes inheriting from Entity should map Id to int column in SQL Server database, but at least one will need to map to long (bigint).
Is it possible to create FluentNH Auto Mapping convention to map those object Ids to int by default? Then we could use another convention or IAutoMappingOverride to handle long Ids.
Thanks!
To answer my own question... It's possible.
You can define convention like this:
internal class PrimaryKeyConvention : IIdConvention
{
public bool Accept(IIdentityPart id)
{
return true;
}
public void Apply(IIdentityPart id)
{
if (<ID should be long>)
id.SetAttribute("type", "Int64");
else
id.SetAttribute("type", "Int32");
}
}

(Fluent) NHibernate - Inhertiance on object level but not on table level

I have the following idea:
Business object implemented as interface or abstract class with certain properties as read only to all layers except the DAL layer. I also want my business objects in another assembly than the DAL (for testing purposes), so marking the properties is not an option for me.
Examples could be one to one relationships or other properties.
I have almost solved the issue by doing the following
abstract class User
{
public virtual long UserId {get; protected set;}
public virtual string Password {get; protected set;}
...
}
In the DAL:
public class DbUser : User
{
internal virtual void SetPassword(string password) {...}
}
I then map this using fluent as
ClassMap<User> {...}
SubclassMap<DbUser> {...}
The problem I get is that fluent tries to create a table named DbUser.
If I skip the SubclassMap and creates a DbUser object and tries to save it I get an "No persister for this object" error.
Is it possible to solve?
You could probably override what is done with Fluent
public class DbUser: IAutoMappingOverride<DbUser>
{
public void Override(AutoMapping<DbUser> mapping)
{
//tell it to do nothing now, probably tell it not to map to table,
// not 100% on how you'd do this here.
}
}
Or you could have an attribute
public class DoNotAutoPersistAttribute : Attribute
{
}
And in AutoPersistenceModelGenerator read for attribute in Where clause to exclude it.
Check would be something like
private static bool CheckPeristance(Type t) {
var attributes = t.GetCustomAttributes(typeof (DoNotAutoPersistAttribute), true);
Check.Ensure(attributes.Length<=1, "The number of DoNotAutoPersistAttribute can only be less than or equal to 1");
if (attributes.Length == 0)
return false;
var persist = attributes[0] as DoNotAutoPersistAttribute;
return persist == null;
}
Then it kind of depends how you're adding entities but you're probably adding via assembly so this might do it for you:
mappings.AddEntityAssembly(typeof(User).Assembly).Where(GetAutoMappingFilter);
....
...
private static bool GetAutoMappingFilter(Type t)
{
return t.GetInterfaces().Any(x => CheckPeristance(x)); //you'd probably have a few filters here
}