zoukankan      html  css  js  c++  java
  • NHibernate 3.2: mapping by code conventions

    After see some characteristic of one of the new NHibernate 3.2 feature it’s the time to see if the mapping by-code gives support to a convention based mapping. In NHibernate there isn’t a real difference between declarative-mapping and convention-based-mapping because every thing live together since the first commit.

    What you will see in this post is defined, by some people, as “auto-mapping”. We don’t have such pretention, and we don’t need to sell something so we are far away to call it auto-mapping but you are free to call it as you want.

    For the coming soon version we took the decision to avoid to override the tables/columns naming-convention provided by NHibernate XML mapping; the same for cascade.

    The domain model

    The model was provided by a NHibernate user: Luka (cluka23)

    NHConventions

    Well… not so complicated but even not so simple Winking smile

    The mapping

    Luka have sent me the conformist-mapping so I can understand which is his target. Only to have a little bit of fun I have added two fields for two collections (see class Application). The whole mapping with conventions and registration in NHibernate’s configuration is:

    1.     var mapper = new ConventionModelMapper();
    2.  
    3.     var baseEntityType = typeof(Entity);
    4.     mapper.IsEntity((t, declared) => baseEntityType.IsAssignableFrom(t) && baseEntityType != t && !t.IsInterface);
    5.     mapper.IsRootEntity((t, declared) => baseEntityType.Equals(t.BaseType));
    6.  
    7.     mapper.BeforeMapManyToOne += (insp, prop, map) => map.Column(prop.LocalMember.GetPropertyOrFieldType().Name + "Id");
    8.     mapper.BeforeMapManyToOne += (insp, prop, map) => map.Cascade(Cascade.Persist);
    9.     mapper.BeforeMapBag += (insp, prop, map) => map.Key(km => km.Column(prop.GetContainerEntity(insp).Name + "Id"));
    10.     mapper.BeforeMapBag += (insp, prop, map) => map.Cascade(Cascade.All);
    11.  
    12.     mapper.Class<Entity>(map =>
    13.     {
    14.         map.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
    15.         map.Version(x => x.Version, m => m.Generated(VersionGeneration.Always));
    16.     });
    17.  
    18.     mapper.Class<Person>(map => map.Property(x => x.Name, pm => pm.Column("PersonName")));
    19.     mapper.Class<Tenant>(map => map.Bag(x => x.AppTenants, cm => cm.Inverse(true), r => { }));
    20.     mapper.Class<Customer>(map => map.Bag(x => x.Tenants, cm => cm.Inverse(true), r => { }));
    21.     mapper.Class<Application>(map =>
    22.     {
    23.         map.Bag(x => x.AppFeatures, cm => cm.Inverse(true), r => { });
    24.         map.Bag(x => x.AppTenants, cm => cm.Inverse(true), r => { });
    25.         map.Bag(x => x.Users, cm => cm.Inverse(true), r => { });
    26.     });
    27.  
    28.     var mapping = mapper.CompileMappingFor(baseEntityType.Assembly.GetExportedTypes().Where(t => t.Namespace.EndsWith("Model")));
    29.  
    30.     nhConf.AddDeserializedMapping(mapping,"LukaModel");

    Line 4: predicate to recognize entities.

    Line 5: predicate to recognize root entities.

    From line 7 to 10: some conventions.

    From line 12 to 16: some specific mapping of some properties strongly mapped using the base Entity class

    From line 18 to 26: some specific mapping of some properties for others entities

    Line 28: the creation of the mapping for the whole domain

    Line 30: registration of the mapping in the NHibernate configuration.

    As you can see there isn’t something special to override conventions, it is all the same you can use with explicit mapping.

    If you can’t resist to have a specific class to override a convention you can use something like this:

    public class ApplicationMapOverrideClassMapping<Application>
    {
        public ApplicationMapOverride()
        {
            Bag(x => x.AppFeatures, cm => cm.Inverse(true), r => { });
            Bag(x => x.AppTenants, cm => cm.Inverse(true), r => { });
            Bag(x => x.Users, cm => cm.Inverse(true), r => { });
        }
    }

    “Ehy!! Fabio, you are wrong!! that class is for conformist-mapping.” No, I’m not wrong. You can use the same identical classes to override your conventions, the same classes you can use for declarative mapping. Not only this but can even mix altogether:

    mapper.Class<Person>(map => map.Property(x => x.Name, pm => pm.Column("PersonName")));
    mapper.Class<Tenant>(map => map.Bag(x => x.AppTenants, cm => cm.Inverse(true), r => { }));
    mapper.Class<Customer>(map => map.Bag(x => x.Tenants, cm => cm.Inverse(true), r => { }));
    mapper.AddMapping<ApplicationMapOverride>();

    “and the two fields ?” those two fields was mapped, don’t worry. If you want see a chuck of the XML:

    <bag name="AppFeatures" access="nosetter.camelcase" inverse="true" cascade="all">
      <key column="ApplicationId" />
      <one-to-many class="AppFeature" />
    </bag>
    <bag name="AppTenants" access="nosetter.camelcase-underscore" inverse="true" cascade="all">
      <key column="ApplicationId" />
      <one-to-many class="AppTenant" />
    </bag>

     NHibernate 3.2 too sexy by far!!!

  • 相关阅读:
    BZOJ3073 Journeys
    UOJ261 【NOIP2016】天天爱跑步 LCA+动态开点线段树
    [bzoj2654] tree 最小生成树kruskal+二分
    【ZJOI2007】【BZOJ1059】矩阵游戏 匈牙利算法
    [Bzoj 2427] [HAOI2010] 软件安装 tarjan缩点+树形DP
    [CQOI2011]放棋子--DP
    BZOJ 3990 排序
    (六)接入层:反向代理,接入层扩容,负载均衡
    (五)伪分布式:你以为,多机就是分布式?
    (四)容量设计:流量高低,对架构究竟有什么影响?
  • 原文地址:https://www.cnblogs.com/sunjie9606/p/2169730.html
Copyright © 2011-2022 走看看