How to make IClassConvention or IIdConvention not override my ClassMap

180 views
Skip to first unread message

JohnRudolfLewis

unread,
Mar 16, 2009, 11:07:12 AM3/16/09
to Fluent NHibernate
I have a domain entity class with a silly long name. My
IClassConvention and IIdConvention end up generating names that are
too long for my database, and I get identifier too long errors. So my
first thought was to specify a WithTable to change the name to an
abbreviation, and to specify a column name with my Id.

But my IClassConvention and IIdConvention overwrite what I specify in
the ClassMap.

So, I need to add some code to the Accept methods. The problem is, I
don't see an obvious way to determine if I had already specified a
table or column name in my ClassMap.

Unless I am missing something obvious, please add a mechanism to avoid
overwriting things I specify in the ClassMap.

James Gregory

unread,
Mar 16, 2009, 11:09:46 AM3/16/09
to fluent-n...@googlegroups.com
There's a TableName property in IClassMap, so you could do: return string.IsNullOrEmpty(target.TableName)

Similarly there's a GetColumnName() method on IIdentityPart.

JohnRudolfLewis

unread,
Mar 16, 2009, 11:13:47 AM3/16/09
to Fluent NHibernate
target.TableName is never null or empty, and neither is GetColumnName.
There is always something there.

On Mar 16, 8:09 am, James Gregory <jagregory....@gmail.com> wrote:
> There's a TableName property in IClassMap, so you could do: return
> string.IsNullOrEmpty(target.TableName)
> Similarly there's a GetColumnName() method on IIdentityPart.
>
> On Mon, Mar 16, 2009 at 3:07 PM, JohnRudolfLewis <JohnRLe...@gmail.com>wrote:
>
>
>
>
>
> > I have a domain entity class with a silly long name. My
> > IClassConvention and IIdConvention end up generating names that are
> > too long for my database, and I get identifier too long errors. So my
> > first thought was to specify a WithTable to change the name to an
> > abbreviation, and to specify a column name with my Id.
>
> > But my IClassConvention and IIdConvention overwrite what I specify in
> > the ClassMap.
>
> > So, I need to add some code to the Accept methods. The problem is, I
> > don't see an obvious way to determine if I had already specified a
> > table or column name in my ClassMap.
>
> > Unless I am missing something obvious, please add a mechanism to avoid
> > overwriting things I specify in the ClassMap.- Hide quoted text -
>
> - Show quoted text -

Brendan Erwin

unread,
Mar 18, 2009, 11:05:53 PM3/18/09
to fluent-n...@googlegroups.com
I have a similar problem. I'm working with a legacy database so my
mappings have lots of column names specified. However, I'd like to use
conventions for new entities but I find that specifying conventions
overrides things specified in my mappings.

So, +1 on a solution to this.

angiel

unread,
Mar 19, 2009, 9:55:06 AM3/19/09
to Fluent NHibernate
This is causing problems for me too. Since converting to the new
conventions, my IAutoMappingOverride classes no longer override the
convention column names. I tried changing the Accept method on my
convention to return string.IsNullOrEmpty(target.GetColumnName()) as
suggested, but the column name is never null or empty because the
default conventions have already been applied.

James Gregory

unread,
Mar 19, 2009, 10:11:49 AM3/19/09
to fluent-n...@googlegroups.com
Ok, there's obviously a flaw in the design here. I'll try to address this.

Jon Kruger

unread,
Mar 19, 2009, 11:13:18 AM3/19/09
to fluent-n...@googlegroups.com
I have a similar problem... I have a convention that sets Cascade.SaveUpdate() on relationships, but I don't really want to do this if someone had explicitly set Cascade in a fluent mapping. 

I think the problem is that when you're in your convention class, there's no way of knowing what has already been set on the mapping (i.e. what values are in _properties).  What would be really nice is if I could do something like this:

(let's say I have an IOneToManyPart named "target")
if (!target.HasBeenSet(t => t.Cascade))
   target.Cascade.SaveUpdate();

Or I might want to do ...
if (!target.HasBeenSet(t => t.Cascade.None()))
   target.Cascade.SaveUpdate();

Just some thoughts.

Jon

Filip Kinsky

unread,
Mar 24, 2009, 6:29:09 AM3/24/09
to Fluent NHibernate
+1 for this kind of solution

I currently also stepped on this issue - I'd like to specify that all
int properties should be defined as "Not.Nullable
().SetAttributeOnColumnElement("default", "0")" unless there is
Nullable() specified in fluent mapping.

On 19 Bře, 16:13, Jon Kruger <krugs...@gmail.com> wrote:
> I have a similar problem... I have a convention that sets
> Cascade.SaveUpdate() on relationships, but I don't really want to do this if
> someone had explicitly set Cascade in a fluent mapping.
>
> I think the problem is that when you're in your convention class, there's no
> way of knowing what has already been set on the mapping (i.e. what values
> are in _properties).  What would be really nice is if I could do something
> like this:
>
> (let's say I have an IOneToManyPart named "target")
> if (!target.HasBeenSet(t => t.Cascade))
>    target.Cascade.SaveUpdate();
>
> Or I might want to do ...
> if (!target.HasBeenSet(t => t.Cascade.None()))
>    target.Cascade.SaveUpdate();
>
> Just some thoughts.
>
> Jon
>
> On Thu, Mar 19, 2009 at 10:11 AM, James Gregory <jagregory....@gmail.com>wrote:
>
> > Ok, there's obviously a flaw in the design here. I'll try to address this.
>

James Gregory

unread,
Mar 25, 2009, 7:12:19 AM3/25/09
to fluent-n...@googlegroups.com
Guys, I've just committed a fix that should remedy this problem.

I think Jon's ideas are great, unfortunately it's a boatload of work. With how fundamentally crippled the conventions were, I couldn't justify the time needed to implement it. I definitely would like to have that kind-of support at some point, but it's too much work right now.

The problem was that the default conventions that FNH uses were being applied before the user conventions, which meant (as you know) your conventions were always being applied on top of existing changes making it impossible to figure out if the changes came from the classmaps or the default conventions. I've now reordered how the conventions are applied so the defaults always come last, after user conventions. As the defaults already don't get applied if anything has been set, this "bug" actually sits nicely with the defaults.

Hope that works out for everyone. Let me know if you have any more trouble.

2009/3/24 Filip Kinsky <fi...@filovo.net>

Billy

unread,
Mar 25, 2009, 8:55:16 AM3/25/09
to Fluent NHibernate
Thank you James!

Billy

Billy

unread,
Mar 25, 2009, 9:41:17 AM3/25/09
to Fluent NHibernate
James,

You state in this thread that it's resolved but in
http://groups.google.com/group/fluent-nhibernate/browse_thread/thread/b0fbb7988b904028
that it cannot be resolved. (I'm hoping the former is true! ;)
Anyway, I just applied latest and found that the override still isn't
overriding the table name convention, as described in the referenced
thread.

Billy

James Gregory

unread,
Mar 25, 2009, 11:43:36 AM3/25/09
to fluent-n...@googlegroups.com
Different issue. This thread is about conventions not overriding classmaps, that other thread is about automapping overrides not overriding conventions. The former (this thread) is fixed, the latter cannot be fixed because automapping overrides always come before conventions.

2009/3/25 Billy <google...@emccafferty.com>

NiHique

unread,
Mar 27, 2009, 4:34:10 PM3/27/09
to Fluent NHibernate
James, I am trying new build, but Convetions still overrides my
ClassMaps, tested by generating hbm files...

e.g. this will result to BatchSize=100 in every ClassMap, but
ClientMap should have BatchSize=666

public class ClassConvention : IClassConvention
{
public bool Accept(IClassMap target) { return true; }
public void Apply(IClassMap target) { target.BatchSize(100); }
}

public class ClientMap : ClassMap<Client>
{
public ClientMap()
{
Id(x => x.Id, "ClientID").GeneratedBy.Native();
BatchSize(666);

James Gregory

unread,
Mar 27, 2009, 4:51:41 PM3/27/09
to fluent-n...@googlegroups.com
That'll be because you're "accepting" everything by just returning true in the Accept method, you need to evaluate whether your batch size has already been set.

I'm pretty sure there isn't a reader property for batch size, so you'll need to check the attributes. Something like this should work:

public bool Accept(IClassMap target)
{
  return !target.HasAttribute("batch-size");
}

2009/3/27 NiHique <kovarik...@gmail.com>

NiHique

unread,
Mar 27, 2009, 5:30:46 PM3/27/09
to Fluent NHibernate
Yes that makes sense - but I cannot find HasAttributte() or HasBeenSet
() method on IClassMap interface.

And from your post above I have make assumption that you have altered
order to 1. conventions > 2. class maps (overrides 1) > 3. FNH
defaults (overrides 1 and 2) - which I think is the way how it should
work...

On Mar 27, 9:51 pm, James Gregory <jagregory....@gmail.com> wrote:
> That'll be because you're "accepting" everything by just returning true in
> the Accept method, you need to evaluate whether your batch size has already
> been set.
> I'm pretty sure there isn't a reader property for batch size, so you'll need
> to check the attributes. Something like this should work:
>
> public bool Accept(IClassMap target)
> {
>   return !target.HasAttribute("batch-size");
>
> }
>
> 2009/3/27 NiHique <kovarik.mar...@gmail.com>

NiHique

unread,
Mar 27, 2009, 5:33:51 PM3/27/09
to Fluent NHibernate
EDIT: eh, ... I mean 3. FNH defaults only overrides 1. and 2. if not
set previously ...

James Gregory

unread,
Mar 27, 2009, 5:41:52 PM3/27/09
to fluent-n...@googlegroups.com
The order is:
  1. Whatever is set in the class map
  2. User created conventions
  3. FNH default conventions
So your conventions still need to check if something has been manually set in the class map.

As for HasAttributes, I got that wrong. There's an Attributes collection with a Has method :)

2009/3/27 NiHique <kovarik...@gmail.com>

NiHique

unread,
Mar 27, 2009, 6:25:41 PM3/27/09
to Fluent NHibernate
Ah, Attributes property - now I feel like idiot :) thanks :)

On Mar 27, 10:41 pm, James Gregory <jagregory....@gmail.com> wrote:
> The order is:
>
>    1. Whatever is set in the class map
>    2. User created conventions
>    3. FNH default conventions
>
> So your conventions still need to check if something has been manually set
> in the class map.
>
> As for HasAttributes, I got that wrong. There's an Attributes collection
> with a Has method :)
>
> 2009/3/27 NiHique <kovarik.mar...@gmail.com>

James Gregory

unread,
Mar 27, 2009, 6:27:27 PM3/27/09
to fluent-n...@googlegroups.com
No problem, I think we're actually inconsistent in this regard.

2009/3/27 NiHique <kovarik...@gmail.com>
Reply all
Reply to author
Forward
0 new messages