Would you help me to translate the above phrase ?
Or perhaps you want know something more ?
I can continue but frankly I have my ba…ehm.. sorry… I mean… I’m something tired of this situation.
Since the begin of FluentNHibernate the attitude was the same: say that NHibernate is a shit and you will be happy. Since the begin of FluentNHibernate we have asked a patch or something and the result was zero lines of code but each time I, or we (the team), do something, somebody come with the same aseptic critics without a single line of C# code. Which is the point ? What mean “Fluent NHibernate is smaller and more flexible than NHibernate” ? More than 600 *.cs files “only” to create a mapping is smaller than what ? an entirely ORM framework ? What is FNH without NHibernate ? bah?!??!?
I done ConfORM yes!! why ? I have asked to the team and the team said “if it will be not ready for 3.0 then please do it out from core” and in that time I was needing something to do a specific big work. Few days ago I have asked again and the team gave me its “OK!!”.
There are people arguing that ConfORM is the same of FluentNHibernate but with an ugly API. WOW!! THANKS!! you are saying that I done the same work, alone and in my free time within less than 3 months, with more flexibility and around 250 *.cs files instead more than 600. But are you really sure that I’m doing the same ? I think that ConfORM is more powerful than FNH but this is not the point. Each time I have published a post about ConfORM some FNH’s fanatics had the pleasure to ask me the same example but using FNH… ehi MAN!! do you haven’t something else to do ? FNH team ask me (not to the team but to me directly) that I have to implement a public API to let FNH avoid XMLs, FNH users ask to me to publish my examples about ConfORM but using FNH…when I implement another public API, to create mapping, again there is something else to do in another way… are you crazy or what ?
The discussion about the API, of explicit mapping, used in NHibernate is again another point where people like to say something. That API was proposed to the team and the team have discussed it (and this is not the first time I’m saying the same as you can read here and here and here if you follow all links in those posts). We “imitate” the XML simplifying it where possible. If a user know XML then he can understand and follow the new API. All existing documentation is reusable. Which was the proposal of some FNH’s fanatic ? “you have to use the API of FNH instead that ugly API”… What ? Which will be the end of FluentNHibernate project if NH includes that API ?
All decisions was and are discussed by the team because NH not only has a big community but even is not “one man show”; NHibernate is a team!! We are following MVCs (Most Valuable Contributors) in our JIRA and around the NET and each year we invite some MVCs to become committers. Because I really care about NHibernate, so much that I have more than 1400 commits only in the core, I’m pushing people to implement more and more options to map it. I’m asking myself the reason because some FluentNHibernate fanatics are so blind to don’t see the point.
After these few words its time to show you the code. This time I’ll not use words as “Map NHibernate using your API” or “Map NHibernate using your DSL” (a vague reference to the recipient of the message) but… well… you will see.
Mapping class-by-class
The target is, using the high-level API of NHibernate 3.2, implement what is needed to use this other final API:public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Id(x => x.Id);
Map(x => x.FirstName);
Map(x => x.LastName);
References(x => x.Store);
}
}
public class LocationMap : ComponentMap<Location>
{
public LocationMap()
{
Map(x => x.Aisle);
Map(x => x.Shelf);
}
}
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Price);
HasManyToMany(x => x.StoresStockedIn)
.Cascade.All()
.Inverse()
.Table("StoreProduct");
Component(x => x.Location);
}
}
public class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Products)
.Cascade.All()
.Table("StoreProduct");
HasMany(x => x.Staff)
.Cascade.All()
.Inverse();
}
}
{
public EmployeeMap()
{
Id(x => x.Id);
Map(x => x.FirstName);
Map(x => x.LastName);
References(x => x.Store);
}
}
public class LocationMap : ComponentMap<Location>
{
public LocationMap()
{
Map(x => x.Aisle);
Map(x => x.Shelf);
}
}
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Price);
HasManyToMany(x => x.StoresStockedIn)
.Cascade.All()
.Inverse()
.Table("StoreProduct");
Component(x => x.Location);
}
}
public class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Products)
.Cascade.All()
.Table("StoreProduct");
HasMany(x => x.Staff)
.Cascade.All()
.Inverse();
}
}
All classes/interfaces needed to reproduce the Fluent-NHibernate’s API using the NHibernate 3.2 high-level API are:
public class ClassMap<T> : IMappingProvider where T : class
{
private readonly ClassMapping<T> mapper = new ClassMapping<T>();
public IdentityPart<T, TProperty> Id<TProperty>(Expression<Func<T, TProperty>> idProperty)
{
return new IdentityPart<T, TProperty>(mapper, idProperty);
}
public PropertyBuilder<T, TProperty> Map<TProperty>(Expression<Func<T, TProperty>> property)
{
return new PropertyBuilder<T, TProperty>(mapper, property);
}
public ManyToOneBuilder<T, TOther> References<TOther>(Expression<Func<T, TOther>> property) where TOther : class
{
return new ManyToOneBuilder<T, TOther>(mapper, property);
}
public IOneToManyPart HasMany<TChild>(Expression<Func<T, IEnumerable<TChild>>> property)
{
// TODO: In FNH you have to find the way to know the type of the collection (Bag,Set,List etc.);
return new OneToManyPart<T, TChild, IBagPropertiesMapper<T, TChild>>(property, mapper.Bag);
}
public IManyToManyPart HasManyToMany<TChild>(Expression<Func<T, IEnumerable<TChild>>> property)
{
// TODO: In FNH you have to find the way to know the type of the collection (Bag,Set,List etc.);
return new ManyToManyPart<T, TChild, IBagPropertiesMapper<T, TChild>>(property, mapper.Bag);
}
public void Component<TComponent>(Expression<Func<T, TComponent>> property) where TComponent: class
{
// TODO: In FNH you have to do the others stuff you need to return the "fluent" interface
mapper.Component(property);
}
IConformistHoldersProvider IMappingProvider.GetNHibernateMapping()
{
return mapper;
}
}
public class ComponentMap<T> : IMappingProvider where T : class
{
private readonly ComponentMapping<T> mapper = new ComponentMapping<T>();
public PropertyBuilder<T, TProperty> Map<TProperty>(Expression<Func<T, TProperty>> property)
{
return new PropertyBuilder<T, TProperty>(mapper, property);
}
IConformistHoldersProvider IMappingProvider.GetNHibernateMapping()
{
return mapper;
}
}
public interface IMappingProvider
{
IConformistHoldersProvider GetNHibernateMapping();
}
public class IdentityPart<T, TProperty> where T : class
{
private readonly ClassMapping<T> mapper;
private readonly Expression<Func<T, TProperty>> idProperty;
public IdentityPart(ClassMapping<T> classMapping, Expression<Func<T, TProperty>> idProperty)
{
this.mapper = classMapping;
this.idProperty = idProperty;
mapper.Id(idProperty, x => { });
}
public IdentityPart<T, TProperty> Column(string columnName)
{
mapper.Id(idProperty, x => x.Column(columnName));
return this;
}
}
public class PropertyBuilder<T, TProperty> where T : class
{
private readonly IPropertyContainerMapper<T> mapper;
private readonly Expression<Func<T, TProperty>> property;
public PropertyBuilder(IPropertyContainerMapper<T> classMapping, Expression<Func<T, TProperty>> property)
{
this.mapper = classMapping;
this.property = property;
mapper.Property(property, x => { });
}
public PropertyBuilder<T, TProperty> Column(string columnName)
{
mapper.Property(property, x => x.Column(columnName));
return this;
}
}
public class ManyToOneBuilder<T, TOther>
where T : class
where TOther : class
{
private readonly ClassMapping<T> mapper;
private readonly Expression<Func<T, TOther>> property;
public ManyToOneBuilder(ClassMapping<T> classMapping, Expression<Func<T, TOther>> property)
{
this.mapper = classMapping;
this.property = property;
mapper.ManyToOne(property, x => { });
}
public ManyToOneBuilder<T, TOther> Column(string columnName)
{
mapper.ManyToOne(property, x => x.Column(columnName));
return this;
}
}
public interface ICollectionAttributesApplier<T, TChild> where T : class
{
void ApplyAttributes(Action<ICollectionPropertiesMapper<T, TChild>> apply);
}
public interface IOneToManyPart
{
ICollectionCascadeExpression<IOneToManyPart> Cascade { get; }
IOneToManyPart Inverse();
}
public class OneToManyPart<T, TChild, TCollectionCustomizer> : ICollectionAttributesApplier<T, TChild>, IOneToManyPart
where T : class
where TCollectionCustomizer : ICollectionPropertiesMapper<T, TChild>
{
private readonly Expression<Func<T, IEnumerable<TChild>>> property;
private readonly Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer;
public OneToManyPart(Expression<Func<T, IEnumerable<TChild>>> property,
Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer)
{
this.property = property;
this.customizer = customizer;
ApplyRelation(x => x.OneToMany());
}
public ICollectionCascadeExpression<IOneToManyPart> Cascade
{
get { return new CollectionCascadeExpression<IOneToManyPart, T, TChild, OneToManyPart<T, TChild, TCollectionCustomizer>>(this, this); }
}
public IOneToManyPart Inverse()
{
ApplyAttributes(x => x.Inverse(true));
return this;
}
public void ApplyAttributes(Action<ICollectionPropertiesMapper<T, TChild>> apply)
{
customizer(property, att => apply(att), rel => { });
}
private void ApplyRelation(Action<ICollectionElementRelation<TChild>> apply)
{
customizer(property, x => { }, apply);
}
}
public interface IManyToManyPart
{
ICollectionCascadeExpression<IManyToManyPart> Cascade { get; }
IManyToManyPart Table(string tableName);
IManyToManyPart Inverse();
}
public class ManyToManyPart<T, TChild, TCollectionCustomizer> : ICollectionAttributesApplier<T, TChild>, IManyToManyPart
where T : class
where TCollectionCustomizer : ICollectionPropertiesMapper<T, TChild>
{
private readonly Expression<Func<T, IEnumerable<TChild>>> property;
private readonly Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer;
public ManyToManyPart(Expression<Func<T, IEnumerable<TChild>>> property,
Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer)
{
this.property = property;
this.customizer = customizer;
ApplyRelation(x => x.OneToMany());
}
public ICollectionCascadeExpression<IManyToManyPart> Cascade
{
get { return new CollectionCascadeExpression<IManyToManyPart, T, TChild, ManyToManyPart<T, TChild, TCollectionCustomizer>>(this, this); }
}
public IManyToManyPart Inverse()
{
ApplyAttributes(x => x.Inverse(true));
return this;
}
public IManyToManyPart Table(string tableName)
{
ApplyAttributes(x => x.Table(tableName));
return this;
}
public void ApplyAttributes(Action<ICollectionPropertiesMapper<T, TChild>> apply)
{
customizer(property, att => apply(att), rel => { });
}
private void ApplyRelation(Action<ICollectionElementRelation<TChild>> apply)
{
customizer(property, x => { }, apply);
}
}
public interface ICollectionCascadeExpression<TParent>
{
TParent All();
TParent DeleteOrphan();
TParent AllDeleteOrphan();
}
public class CollectionCascadeExpression<TParent, TContainer, TChild, TApplier> : ICollectionCascadeExpression<TParent>
where TParent : class
where TContainer : class
where TApplier : ICollectionAttributesApplier<TContainer, TChild>
{
private readonly TParent parent;
private readonly TApplier applier;
public CollectionCascadeExpression(TParent parent, TApplier applier)
{
this.parent = parent;
this.applier = applier;
}
public TParent All()
{
applier.ApplyAttributes(x => x.Cascade(Cascade.All));
return parent;
}
public TParent DeleteOrphan()
{
applier.ApplyAttributes(x => x.Cascade(Cascade.DeleteOrphans));
return parent;
}
public TParent AllDeleteOrphan()
{
applier.ApplyAttributes(x => x.Cascade(Cascade.All.Include(Cascade.DeleteOrphans)));
return parent;
}
}
{
private readonly ClassMapping<T> mapper = new ClassMapping<T>();
public IdentityPart<T, TProperty> Id<TProperty>(Expression<Func<T, TProperty>> idProperty)
{
return new IdentityPart<T, TProperty>(mapper, idProperty);
}
public PropertyBuilder<T, TProperty> Map<TProperty>(Expression<Func<T, TProperty>> property)
{
return new PropertyBuilder<T, TProperty>(mapper, property);
}
public ManyToOneBuilder<T, TOther> References<TOther>(Expression<Func<T, TOther>> property) where TOther : class
{
return new ManyToOneBuilder<T, TOther>(mapper, property);
}
public IOneToManyPart HasMany<TChild>(Expression<Func<T, IEnumerable<TChild>>> property)
{
// TODO: In FNH you have to find the way to know the type of the collection (Bag,Set,List etc.);
return new OneToManyPart<T, TChild, IBagPropertiesMapper<T, TChild>>(property, mapper.Bag);
}
public IManyToManyPart HasManyToMany<TChild>(Expression<Func<T, IEnumerable<TChild>>> property)
{
// TODO: In FNH you have to find the way to know the type of the collection (Bag,Set,List etc.);
return new ManyToManyPart<T, TChild, IBagPropertiesMapper<T, TChild>>(property, mapper.Bag);
}
public void Component<TComponent>(Expression<Func<T, TComponent>> property) where TComponent: class
{
// TODO: In FNH you have to do the others stuff you need to return the "fluent" interface
mapper.Component(property);
}
IConformistHoldersProvider IMappingProvider.GetNHibernateMapping()
{
return mapper;
}
}
public class ComponentMap<T> : IMappingProvider where T : class
{
private readonly ComponentMapping<T> mapper = new ComponentMapping<T>();
public PropertyBuilder<T, TProperty> Map<TProperty>(Expression<Func<T, TProperty>> property)
{
return new PropertyBuilder<T, TProperty>(mapper, property);
}
IConformistHoldersProvider IMappingProvider.GetNHibernateMapping()
{
return mapper;
}
}
public interface IMappingProvider
{
IConformistHoldersProvider GetNHibernateMapping();
}
public class IdentityPart<T, TProperty> where T : class
{
private readonly ClassMapping<T> mapper;
private readonly Expression<Func<T, TProperty>> idProperty;
public IdentityPart(ClassMapping<T> classMapping, Expression<Func<T, TProperty>> idProperty)
{
this.mapper = classMapping;
this.idProperty = idProperty;
mapper.Id(idProperty, x => { });
}
public IdentityPart<T, TProperty> Column(string columnName)
{
mapper.Id(idProperty, x => x.Column(columnName));
return this;
}
}
public class PropertyBuilder<T, TProperty> where T : class
{
private readonly IPropertyContainerMapper<T> mapper;
private readonly Expression<Func<T, TProperty>> property;
public PropertyBuilder(IPropertyContainerMapper<T> classMapping, Expression<Func<T, TProperty>> property)
{
this.mapper = classMapping;
this.property = property;
mapper.Property(property, x => { });
}
public PropertyBuilder<T, TProperty> Column(string columnName)
{
mapper.Property(property, x => x.Column(columnName));
return this;
}
}
public class ManyToOneBuilder<T, TOther>
where T : class
where TOther : class
{
private readonly ClassMapping<T> mapper;
private readonly Expression<Func<T, TOther>> property;
public ManyToOneBuilder(ClassMapping<T> classMapping, Expression<Func<T, TOther>> property)
{
this.mapper = classMapping;
this.property = property;
mapper.ManyToOne(property, x => { });
}
public ManyToOneBuilder<T, TOther> Column(string columnName)
{
mapper.ManyToOne(property, x => x.Column(columnName));
return this;
}
}
public interface ICollectionAttributesApplier<T, TChild> where T : class
{
void ApplyAttributes(Action<ICollectionPropertiesMapper<T, TChild>> apply);
}
public interface IOneToManyPart
{
ICollectionCascadeExpression<IOneToManyPart> Cascade { get; }
IOneToManyPart Inverse();
}
public class OneToManyPart<T, TChild, TCollectionCustomizer> : ICollectionAttributesApplier<T, TChild>, IOneToManyPart
where T : class
where TCollectionCustomizer : ICollectionPropertiesMapper<T, TChild>
{
private readonly Expression<Func<T, IEnumerable<TChild>>> property;
private readonly Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer;
public OneToManyPart(Expression<Func<T, IEnumerable<TChild>>> property,
Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer)
{
this.property = property;
this.customizer = customizer;
ApplyRelation(x => x.OneToMany());
}
public ICollectionCascadeExpression<IOneToManyPart> Cascade
{
get { return new CollectionCascadeExpression<IOneToManyPart, T, TChild, OneToManyPart<T, TChild, TCollectionCustomizer>>(this, this); }
}
public IOneToManyPart Inverse()
{
ApplyAttributes(x => x.Inverse(true));
return this;
}
public void ApplyAttributes(Action<ICollectionPropertiesMapper<T, TChild>> apply)
{
customizer(property, att => apply(att), rel => { });
}
private void ApplyRelation(Action<ICollectionElementRelation<TChild>> apply)
{
customizer(property, x => { }, apply);
}
}
public interface IManyToManyPart
{
ICollectionCascadeExpression<IManyToManyPart> Cascade { get; }
IManyToManyPart Table(string tableName);
IManyToManyPart Inverse();
}
public class ManyToManyPart<T, TChild, TCollectionCustomizer> : ICollectionAttributesApplier<T, TChild>, IManyToManyPart
where T : class
where TCollectionCustomizer : ICollectionPropertiesMapper<T, TChild>
{
private readonly Expression<Func<T, IEnumerable<TChild>>> property;
private readonly Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer;
public ManyToManyPart(Expression<Func<T, IEnumerable<TChild>>> property,
Action<Expression<Func<T, IEnumerable<TChild>>>, Action<TCollectionCustomizer>, Action<ICollectionElementRelation<TChild>>> customizer)
{
this.property = property;
this.customizer = customizer;
ApplyRelation(x => x.OneToMany());
}
public ICollectionCascadeExpression<IManyToManyPart> Cascade
{
get { return new CollectionCascadeExpression<IManyToManyPart, T, TChild, ManyToManyPart<T, TChild, TCollectionCustomizer>>(this, this); }
}
public IManyToManyPart Inverse()
{
ApplyAttributes(x => x.Inverse(true));
return this;
}
public IManyToManyPart Table(string tableName)
{
ApplyAttributes(x => x.Table(tableName));
return this;
}
public void ApplyAttributes(Action<ICollectionPropertiesMapper<T, TChild>> apply)
{
customizer(property, att => apply(att), rel => { });
}
private void ApplyRelation(Action<ICollectionElementRelation<TChild>> apply)
{
customizer(property, x => { }, apply);
}
}
public interface ICollectionCascadeExpression<TParent>
{
TParent All();
TParent DeleteOrphan();
TParent AllDeleteOrphan();
}
public class CollectionCascadeExpression<TParent, TContainer, TChild, TApplier> : ICollectionCascadeExpression<TParent>
where TParent : class
where TContainer : class
where TApplier : ICollectionAttributesApplier<TContainer, TChild>
{
private readonly TParent parent;
private readonly TApplier applier;
public CollectionCascadeExpression(TParent parent, TApplier applier)
{
this.parent = parent;
this.applier = applier;
}
public TParent All()
{
applier.ApplyAttributes(x => x.Cascade(Cascade.All));
return parent;
}
public TParent DeleteOrphan()
{
applier.ApplyAttributes(x => x.Cascade(Cascade.DeleteOrphans));
return parent;
}
public TParent AllDeleteOrphan()
{
applier.ApplyAttributes(x => x.Cascade(Cascade.All.Include(Cascade.DeleteOrphans)));
return parent;
}
}
The code used for the method to build the SessionFactory is:
private static ISessionFactory CreateSessionFactory()
{
var configure = new Configuration();
configure.DataBaseIntegration(x =>
{
x.Dialect<MsSql2008Dialect>();
x.ConnectionString = (new SqlConnectionStringBuilder
{
DataSource = @"localhost\SQLEXPRESS",
InitialCatalog = "reFNH",
IntegratedSecurity = true
}).ToString();
x.SchemaAction = SchemaAutoAction.Recreate;
});
return configure.AddMappingsFromAssemblyOf<Program>().BuildSessionFactory();
}
{
var configure = new Configuration();
configure.DataBaseIntegration(x =>
{
x.Dialect<MsSql2008Dialect>();
x.ConnectionString = (new SqlConnectionStringBuilder
{
DataSource = @"localhost\SQLEXPRESS",
InitialCatalog = "reFNH",
IntegratedSecurity = true
}).ToString();
x.SchemaAction = SchemaAutoAction.Recreate;
});
return configure.AddMappingsFromAssemblyOf<Program>().BuildSessionFactory();
}
The extension method to add all mappings using the new implementations is:
public static Configuration AddMappingsFromAssemblyOf<T>(this Configuration conf)
{
var mapper = new ModelMapper();
mapper.BeforeMapClass += (mi, t, cam) => cam.Id(x => x.Generator(Generators.Native));
foreach (Type type in typeof(T).Assembly.GetExportedTypes().Where(x => typeof(IMappingProvider).IsAssignableFrom(x) && !x.IsGenericTypeDefinition && !x.IsInterface))
{
IMappingProvider mappingInstance;
try
{
mappingInstance = (IMappingProvider)Activator.CreateInstance(type);
}
catch (Exception e)
{
throw new MappingException("Unable to instantiate mapping class (see InnerException): " + type, e);
}
mapper.AddMapping(mappingInstance.GetNHibernateMapping());
}
conf.AddDeserializedMapping(mapper.CompileMappingForAllExplicitAddedEntities(), "Domain");
return conf;
}
{
var mapper = new ModelMapper();
mapper.BeforeMapClass += (mi, t, cam) => cam.Id(x => x.Generator(Generators.Native));
foreach (Type type in typeof(T).Assembly.GetExportedTypes().Where(x => typeof(IMappingProvider).IsAssignableFrom(x) && !x.IsGenericTypeDefinition && !x.IsInterface))
{
IMappingProvider mappingInstance;
try
{
mappingInstance = (IMappingProvider)Activator.CreateInstance(type);
}
catch (Exception e)
{
throw new MappingException("Unable to instantiate mapping class (see InnerException): " + type, e);
}
mapper.AddMapping(mappingInstance.GetNHibernateMapping());
}
conf.AddDeserializedMapping(mapper.CompileMappingForAllExplicitAddedEntities(), "Domain");
return conf;
}
Conclusion
Now not only you have the API you was asking for 3 years (implemented as we need) but you have even the starting point to use it in Fluent-NHibernate and put the turbo to your framework. If you want/need you can use a more low-level API; the name space where look is NHibernate.Mapping.ByCode.Impl .If you need something else, please let me know.P.S. About “”auto”” mapping I’ll be back soon.
you are crazy idiot
ReplyDeleteI don't understand what is this all about?
ReplyDeleteIf someone like FNH, he can use it. If someone likes ConfORM - use it. But why fight about which is better?
Fabio, don't listen stupid people.
ReplyDeleteYou are doing a great job!
Thanks you a lot!
Greetings from Ukraine.
Exactly
DeleteAlexey, ты тупой идиот
ReplyDeleteAlexey is right: why don't we all do what we want and don't bother about what the other is doing? There is room and opportunities for everyone.
ReplyDeleteСаша, логику включи. А лучше мозг.
ReplyDeleteХамством ты показываешь свой уровень развития и интеллекта.
Alexey, Фабио пытается оправдать свои действия, доказать всем, что его тупая хуйня кому-то нужна. Но это не так. Это изобретение колеса, причем колеса квадратного, которое не поедет. Все, кто держит его сторону - тупые идиоты.
ReplyDeleteFabio, will you continue to support ConORM?
ReplyDeleteСлушай, зачем услажнять себе жизнь? Зачем создавать мапинг на каждый класс? У меня вся модель замалена в одном методе, порядка 70 строчек кода. Такое можно сделать в FNH?
ReplyDelete>Такое можно сделать в FNH?
ReplyDeleteКонечно, только гораздо удобнее, чем, предложенное здесь, шаманство с лямбдами.
Можешь показать пример?
ReplyDeletehttp://wiki.fluentnhibernate.org/Auto_mapping
ReplyDeleteПо поводу лямбд, это очень удобно к примеру при рефакторинге. В FNH у тебя имена описаны строками. т.е. либо у тебя должно быть куча тестов либо лямбда. если это не так покажи пример.
ReplyDeleteОк, доля правды есть. Я FNH глубоко не копал, считаю confORM\"mapping by code" более гибким. Если тебе так сильно не нравится линк и новые фичи юзай FNH. Не нужно наезжать на людей, развивающих проект. Выбор всегда хорошо.
ReplyDeleteАлександр, Фабио никому ничего доказывать не нужно, тем более оправдываться. Он делает хороший продукт, кто-то его использует, кому-то нравится, кто-то нет.
ReplyDeleteА вот ты вылез и орешь на всю глотку - какой ты, бля, умный и какие все вокруг идиоты. А ты что сделал для community?
Жду ответа. Нет ответа - обосрался.
Криворучко Юрий, руки выпрями;) Если ему не нужно ничего доказывать и не нужно оправдываться, то почему он оправдывается и что-то кому-то доказывает?
ReplyDeleteAlexey, выбор в пользу квадратного колеса - говно.
ReplyDeleteШуток по поводу моей фамилии я не слышал со школы. Наталкивает на размышлении об уровне твоего интелекта.
ReplyDeleteДа, кстати - обосрался!
Александр. Меня теперь интерисует, потрешь ли ты свой срач?
ReplyDeleteБольшенство обосранцев так и делают, чтобы в конец не опозориться.
Криворучко Юрий, ищущий, да найдет;) я не Фабио и не собираюсь ничего никому доказывать. И, да, я очень рад, что твой запор прошел и ты наконец-то смог просраться, но мне очень неприятно, что ты пишешь об этом здесь.
ReplyDelete@Fabio: if people opposite to this changes to NH core maybe you should stop, and think about it?
Криворучко Юрий, меня уже порядком подзаебало твое копрофильство. Вытри его, а?
ReplyDeleteВот небольшая часть моего вклада в OSS http://xunitcontrib.codeplex.com/SourceControl/network/Forks/hazzik/xunitcontribR6 но из-за тупых идиотов с NIH syndrome он не попал в основную ветку, и очередной велосипедист изобрел свое квадратное колесо, которое даже не покатилось.
Саша, ты мудак. Не обижайся, но это правда.
ReplyDeleteИди погуляй отсюда. И вообще юзай ADO. Как раз для тебя.
Alexey, если что, мудак - человек с яйцами. Если ты кастрат, то мне тебя жаль.
ReplyDeleteЕсли по существу - NH очень удобная ORM, она мне очень нравится, но последнее время меня раздражают новые квадратные колёса, которые попадают в core, благодаря Фабио.
Fabio, just ignore the people complaining. It's your time and you can do what ever the heck you want with it. If people don't like the new additions to NHibernate, well... don't use them. Is it that hard?.
ReplyDeleteGood job to you and all of the NHibernate team!
XreiX, if people dont like changes, probably better do not introduce that changes?
ReplyDeletehazzik, I'm more than sure more people than not will appreciate the change.
ReplyDeleteАлександр.
ReplyDelete>> но из-за тупых идиотов с NIH syndrome он не попал в основную ветку
То есть ничего не сделал.
Let people make the choice
ReplyDeleteКриворучко Юрий, сам-то ты что сделал?
ReplyDeleteHazzik, as with everything open source, don't like it? Don't use it. The changes won't break what you currently have.
ReplyDelete@Rei, I like NH, but i do not like that features, so i have no choice. There is better way - make model-centric configuration with differnet providers like xml, fluent-nh, confORM and other.
ReplyDeletehazzik, what part of "You don't HAVE to use that feature" don't you understand?
ReplyDeleteСаша, мы с Алексеем разработали и запустили MES системы с интеграцией на более чем 7ми крупных заводах пищевой промышленности.
ReplyDeleteЯ и не претендую на роль активного учасника процесса, это ты претендуешь, я пользователь. И как пользователь скажу: let people make the choice.
Криворучко Юрий, дак что ты сделал для сообщества?
ReplyDeleteRei, i do not want to have features that useless for me, let they be in addons or something else.
ReplyDeleteAs stated, they are useless for you, but useful for others, I particularly appreciate not having yet another assembly to have to reference/keep up to date, apart from the fact that it does exactly what it should, configure NHibernate by code.
ReplyDeleteThere is no difference between referencing one or two assemblies.
ReplyDeleteI think this whole snafu demonstrates that I was barking up the right tree with my posts on using typed xml mappings using Linq To XSD to write your OWN fluent mapping librart.
ReplyDeleteEveryone is familiar with xml, and everyone has a different idea of how the fluent interface should look. Give everyone a typed interface to NH mappings that resembles the xml mappings as much as is possible (which is why generation off the xsd is a good approach), and then the Fluent config libraries are just external contrib libraries.
Hazzik,
ReplyDeleteWhy don't you compile NHibernate yourself without mapping by code? It's easy, just exclude the folder. There is no dependency on it.
@rjperes, maybe I should write my own NHibernate?
ReplyDelete@Harry
ReplyDeleteWhat you call Linq To XSD in already there since NH2.0 and the work to let people use it was publisched with NH3.0. Have a look to all claases named Hbm*.
Thanks Fabio, I remember having a look at them before but they weren't quite able to do what I thought they needed to.
ReplyDeletee.g. if you try and replicate the mappings as in
this example using the NHibernate.Cfg.MappingSchema namespace, you can't achieve as clean a mapping as you can with the LinqToXSD generated library.
This is because there aren't any typed collections on the HbmMapping object which suggest what can be added as child elements. There are some untyped object[] properties, but it's not very intuitive compared to a List, and you can't use an object initializer with an array.
With a bit of sugar (or a different generator) that namespace would be a great foundation for all the various fluent libraries people want to use, and the fluent libraries could live outside the main NH project.
@Harry
ReplyDeleteUse what fit your needs and let NHibernate's team choose what the team think is good for the project they are working on.
At each release we have increased the number of downloads and the number of users... we are doing everything possible to kill NHibernate but we are failing.
Hey Fabio, I learned a lot of russian with this post. Thanks.
ReplyDeleteПетух в духовке, есть хорошая неделя.
If this new (whatsitcalled, Sexy? :)) API is like ConfORM than it is more flexible than Fluent NHibernate, since FNH doesn't support modification of existing mappings. Also, parsing of hbm.XMLs is hurting my application's startup time, and FNH would make it even worse. That said, I think FNH is nice, and I really support the idea of rewriting it to skip the XML step: in that case, I would use FNH for static mappings (because it's easier) and ConfORM or Sexy for dynamic (because it's more powerful).
ReplyDeleteThanks, I found this post very helpful. I'd seen some of the ConfORM posts before but I'd never quite picked up the context. I do like the closeness to the .hbm vocabulary.
ReplyDeleteWith Mapping By Code forming part of the NH Core, I guess at some point the Reference document will cover it? Which should make adoption on new projects a pretty obvious option.
Fabio,
ReplyDeleteConfORM is simply another GREAT way to mapping aur class
thanks for ALL
@Alexey
ReplyDeleteYes, at least while ConfORM will have better support to discover implementation patterns and apply mapping-patterns.
The implementation in NHibernate3.2 is a simplification done to give a public API to avoid XML and a simplified support of "conventions-based" mapping.
Alexey, for the next time: don't waste your time!
Just use what fits yours needs and leave people do the same.
@hazzik
ReplyDelete"if people opposite to this changes to NH core maybe you should stop, and think about it?"
It depend on who are those people. You aren't a good candidate to be listened.
I would like to thank all developers who was involved into NHibernate, FluentNHibernate and ConfORM projects.
ReplyDeletePersonally I'm sure that having an alternatives is the best part of open source projects.
@Fabio
Thank you for this particular post.
The most important that I saw in this post that you in general is not against FluentNHibernate project and it's API.
As far as I understand people just annoys you askin the same questions again and again.
Moreover, I was really surprised and glad that you made some effort and show the way how FluentNHibernate's DSL could be rewritten in order to use API from ConfORM project.
Despite the fact that ConfORM in some point looks more complicated for me I really like additional power and flexibility of it's API.
ConfORM don't dictate the way how I should arrange and organize my mapping code. That is very good.
Right now I'm using FluentNHibernate in my work but I will definitely will try ConfORM in near near future.
Thank you again!
@Fabio Maulo
ReplyDeleteSometimes you have to stop, to avoid get a piece of shit like Winamp or ACDSee. They have not stopped.
@Fabio Maulo
ReplyDeletePlz change the settings of your RSS feed to show the full content of the posts. thanks!
I love that people post in all the languages. But Fluent 1.2 is last release of FNH then how I upgrade to nH 3.2? I have other things to do in my project than writing mapping again. Sigh!!! I just started my project and I end up here. What is the situation of other people.
ReplyDeleteI can't resist to give my opinion about the ongoing discussion about Loquacious and Fluent. (I know it won't stop people from fighting. But I promise to give my opinion only *once* and would appreciate if everyone would follow my example ;-)
ReplyDeleteWhat a shame that some people of Fluent and NH are fighting that much. I know OSS projects which have been killed because of that. *So please stop it now!* There is no reason to fight! Everything is going exactly the way it should.
The new features here look very generic and powerful, which are important properties of a core feature.
There is and should be always space for contribution components. Non-core projects have a big advantage: They can be more specific to a certain usage or kind of project. They should make use of that big freedom!
Many things are just a matter of taste. Once I wrote on stackoverflow: "The terms in the mapping are relational terms. (Fluent tries to "beautify" them a bit which makes it worse IMO. (...))".
http://stackoverflow.com/questions/3036784/fluent-nhibernate-foreign-key-violation-or-null-values/3037151#3037151
well, the problem is NH team has not the army of article writers such as MS teams. FHN has a good learning resources around the web, but what about this new sexy one?
ReplyDeleteFirst I appreciate the effort of NH-Team and Fabio for confORM and mapping-by-code.
ReplyDeleteBut there is another side of "dont use it if you don't like". I'm in the same position as 'us'. I started with FNH which was the best option in that time and now i'm stuck. It's good to have the choice, but it's also good to dont have to invest a lot of time finding the right choice, or to have to split forces writing code and documentation. That this is a problem is best seen in the lack of documentation for this new sexy way, because many still use FNH and wont/can't write documentation for it.
My conclusion: there are downsides to create different solutions for the same problem.
PS: please dont see this as discredit, it's just my view as a User
@Ronald
ReplyDeleteIn 4 months NH has 50k downloads (sourceforge+nuget). Can you imagine a 80characters line per each download?
With NHForge we gave a open WIKI and a pretty open blog-space allowing cross posting...
Around one year we was looking even for a payed guy to write doc...
PS: please see it just as the point of view from a OSS developer.
@Fabio thanks for the answer.
ReplyDeleteHowever I'm not sure what you mean by "Can you imagine a 80characters line per each download?"
@Roland
ReplyDeleteIf each one have downloaded NH would contribute a line of documentation we will have a huge book.
The current on-line reference is composed by 11356 words... even the contribution of just a word per download could be enough.
That is what I mean.
I am using c#.net and we are using fluent nhibernate. It was fine until i was connecting to a single database. Now in the same project i am suppose to use multiple database, how can this be achieved. Configuration of the fluent nhibernate is lies in web/app.config file. How to specify multiple connection string over there and how to create multiple session factories. Please suggest
ReplyDelete