【问题标题】:Composite primary key declaration through Convention for fluent-nHibernate通过 fluent-nHibernate 约定的复合主键声明
【发布时间】:2011-10-20 19:05:34
【问题描述】:

我需要对具有复合主键(Azure 表,主键为 (PartitionKey,RowKey) 的表使用 Fluent-nHibernate,并且我想将它们与实体上的相应属性(或组件属性,如果更容易)

我的桌子看起来像:

{
  PartitionKey PK,
  RowKey PK,
  [..]
}

和实体

public class MyRecord
{
  public virtual string PartitionKey{get;set;}
  public virtual string RowKey{get;set;}

  [...]
}

我当前的项目使用针对 AzureTable 的自定义 nHibernate 驱动程序。

我设法使它与 ClassMap 或 XML 映射一起工作。因此,我确信驱动程序正在工作。此外,Azure 表 HTTP 请求使用类映射或 XML 声明是正确的。

但是我确实需要约定,所以这不是一个可接受的解决方案。

最后,始终可以选择仅将 RowKey 映射为 PK,即使 Datastore 使用 (PartitionKey,RowKey)。它也可以工作,但是它并不真正令人满意,因为它在 nHibernate 和底层数据存储之间引入了唯一性处理不匹配。

更新:

我尝试构建一个自定义的 IIdentityConvention。 IIdentityInstance.Column() 方法只考虑第一次调用。 但是,如果我使用反射将两列都添加到底层映射字段,配置构建将失败并出现 XML 验证异常(需要属性“类”)

【问题讨论】:

    标签: nhibernate fluent-nhibernate azure


    【解决方案1】:

    我今天让它工作了,但它并不漂亮。它也不使用约定。据我了解,它们实际上是为了在主映射发生后进行调整。我认为添加映射超出了约定的范围。

    在我的项目中,我有一个通用的基于自动映射的初始化过程,它对类型一无所知,但对复合键具有依赖注入映射覆盖。不完全是您的情况,但这是一个类似的问题。

    我通过反射来实现这一点的方法是获取适当的 AutoPersistenceModel 对象。如果您的代码如下所示:

    Fluently.Configure().Mappings(m => ...
    

    AutoPersistenceModel 对象是 m.AutoMappings.First()

    从这里开始,这是一项非常严肃的反射工作,最终调用了 FluentNHibernate 中的受保护方法。这是我正在使用的代码:

        private void Override(AutoPersistenceModel container, 
                              Type type, 
                              IEnumerable<KeyValuePair<string,string>> compositeKeys)
        {
            // We need to call container.Override<T>(Action<Automapping<T>> populateMap)
            // Through reflection...yikes
            var overrideMethod = typeof(AutoPersistenceModel)
                                   .GetMethod("Override")
                                   .MakeGenericMethod(type);
            var actionFactoryMethod = typeof(FluentNHibernateInitializer)
                                        .GetMethod("CompositeMapperFactory",
                                           BindingFlags.Instance | BindingFlags.NonPublic)
                                        .MakeGenericMethod(type);
            var actionMethod = actionFactoryMethod
                                 .Invoke(this, new object[] { compositeKeys });
            overrideMethod.Invoke(container, new object[] {actionMethod});
        }
    
        private Action<AutoMapping<T>> CompositeMapperFactory<T>
               (IEnumerable<KeyValuePair<string, string>> compositeKeys)
        {
            return new Action<AutoMapping<T>>(m =>
                {
                    var compositeId = m.CompositeId();
                    foreach (var kvp in compositeKeys) 
                        compositeId = 
                          AddKeyProperty(
                            compositeId, 
                            typeof(T).GetProperty(kvp.Key), 
                            kvp.Value);
                }
            );
        }
    
        /// <summary>
        /// Uses reflection to invoke private and protected members!
        /// </summary>
        /// <param name="compositeId"></param>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        private CompositeIdentityPart<T> AddKeyProperty<T>
          (CompositeIdentityPart<T> compositeId, 
           PropertyInfo propertyInfo, 
           string column)
        {
            var member = FluentNHibernate.MemberExtensions.ToMember(propertyInfo);
            var keyPropertyMethod = typeof(CompositeIdentityPart<T>)
                                      .GetMethod("KeyProperty", 
                                         BindingFlags.Instance | BindingFlags.NonPublic);
            return (CompositeIdentityPart<T>)
                     keyPropertyMethod
                       .Invoke(compositeId, new object[] { member, column, null });
        }
    

    【讨论】:

    • 谢谢!它可以工作,即使我最终放弃了 nHibernate 来访问我的 Azure 表(也许我会再试一次......)
    猜你喜欢
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 2012-01-13
    相关资源
    最近更新 更多