将动态组件映射到不友好的数据表结构

本文关键字:数据表 结构 不友好 动态 组件 映射 | 更新日期: 2023-09-27 18:30:56

我有一个具有以下结构的数据表:

MyTable
-------------------------------------
rule_name      char(20)     PK
value_type     char(20)     PK
value          varchar(50)  not null
dt_last_update datetime     not null

在此表中表示的数据中,我有一个感兴趣的rule_name

MailboxSC

我有两个不同的属性或称之为value_type

numberOfEmails
dateTimeReceived

我无法控制,也没有任何权力。

使用DynamicObject,我遵循了Ayende Rahien所能做到的:

使用 NHibernate 和 .NET 4.0 支持动态字段

所以现在,我的模型。

电子邮件指示器

public class EmailIndicator {
    public EmailIndicator(HashtableDynamicObject hastableDynamicObject) {
        this.hashtableDynamicObject = hashtableDynamicObject;
    }
    public virtual dynamic Attributes { get { return hashtableDynamicObject; } }
    private readonly HashtableDynamicObject hashtableDynamicObject;
}

HashtableDynamicObject

public class HashtableDynamicObject : DynamicObject {
    public HashtableDynamicObject(IDictionary dictionary) {
        this.dictionary = dictionary;
    }
    public override bool TryGetMember(GetMemberBinder binder
        , object[] indexes
        , out object result) {
        result = dictionary[binder.Name];
        return dictionary.Contains(binder.Name);
    }
    public override bool TrySetMember(SetMemberBinder binder
        , object[] indexes
        , object value) {
        dictionary[binder.Name] = value;
        return dictionary.Contains(binder.Name);
    }
    public override bool TryGetIndex(GetIndexBinder binder
        , object[] indexes
        , out object result) {
        result = dictionary[indexes[0]];
        return dictionary.Contains(indexes[0]);
    }
    public override bool TrySetIndex(SetIndexBinder binder
        , object[] indexes
        , object value) {
        dictionary[indexes[0]] = value;
        return dictionary.Contains(indexes[0]);
    }
    private readonly IDictionary dictionary;
}

现在,我想将动态属性映射到rule_name MailboxSC的每一行,以便:

declare @emailCount             int
declare @oldestDateTimeReceived datetime
select (
        select valeur 
            from bqt001_pilotage_indicateurs 
            where nom_regle like 'boiteCourrielSC'
                and type_valeur like 'nombreCourriels'
      ) as emailCount
      , (
        select valeur as olsdestDateTimeReceived
            from bqt001_pilotage_indicateurs
            where nom_regle like 'boiteCourrielSC'
                and type_valeur like 'dateHeurePlusVieux'
      ) as oldestDateTimeReceived
    into @emailCount
        , @oldestDateTimeReceived

因此,我得到了所需的值,电子邮件数量和收到的最早日期/时间。

如何使用经典的NHibernateXML映射或Fluent NHibernate映射它?

链接的Ayende Rahien的文章提供了第一种方法:

<class name="Customer"
       table="Customers">
    <id name="Id">
        <generator class="identity"/>
    </id>
    <property name="Name" />
    <join table="Customers_Extensions" optional="false">
        <key column="CustomerId"/>
        <dynamic-component name="Attributes" access="field.lowercase">
            <property name="EyeColor" type="System.String"/>
        </dynamic-component>
    </join>
</class>

所以我的猜测是:

<class name="EmailIndicatorModel">
    <join table="MyTable" optional="false">
        <dynamic-component name="Attributes" access="field.lowercase">
            <property name="EmailCount" type="System.Int32" />
            <property name="OldestDateTimeReceived" type="System.DateTime" />
        <dynamic-component>
    </join>
</class>

再说一次,这不允许我提及每个属性的鉴别器列rule_namevalue_type

我注定要使用旧式 ADO.NET 吗?

以下是一些关于我感兴趣的有趣的文章:

  • 动态组件流畅自动映射
  • 按代码映射 - 动态组件
  • NHibernate将类属性映射到行而不是列(这篇文章把我引到了Ayende Rahien的文章)

将动态组件映射到不友好的数据表结构

我试图将我们使用NHibernate进行动态映射的可能性放在一起:

NHibernate动态映射

我个人确实使用并从<dynamic-component>中获利很多,但正如上面的资源中所解释的,这需要不同的结构。

我。 IDictionary

因此,首先是客户非常普通/标准的表格:

// [Customer] table with key Customer_ID
Customer_ID, Name, Code,...
          1,  Abc,  xxx,.. 
          2,  Def,  yyy,.. 

键列Customer_ID ,以及描述客户的列。现在,如果我们想使用IDictionary(或 C# 动态对象)<dynamic-component>来扩展客户,我们需要这样的表:

// [CustomerAttributes] - with a key referencing Customer table via Customer_ID
Customer_ID, Attribute1, Attribute2, Attribute3, ...
          1,        123, 2014-01-01,      FALSE, ...
          2,        456, 2015-01-01,       TRUE, ...

这是候选人

<join table="CustomerAttributes" optional="false">
    <key column="Customer_ID"/>
    <dynamic-component name="Attributes">
        <property name="Prop1" column="Attribute1" type="int"/>
        <property name="Prop2" column="Attribute2" type="DateTime"/>
        <property name="Prop3" column="Attribute3" type="bool"/>
    </dynamic-component>
</join>

优势?我们可以使用 ORDER BY。事实上,我们可以使用任何东西(选择 - 投影 - 请参阅此自定义ResultTransformer<dynamic-component>一起使用,其中...

但是必须有标准表,其中属性IDictionary键)由列表示。

IDictionary<T,U>

在问题中提到的表格的情况下

MyTable
-------------------------------------
rule_name      char(20)     PK
value_type     char(20)     PK
value          varchar(50)  not null
dt_last_update datetime     not null

我们需要IDictinary<T, U>,并用<map>映射

<map name="Attributes" table="MyTable" >
    <key column="rule_name"/>
     <index-many-to-many column="value_type" class="ValueType"/>
     <element column="value" type="string"/>
</map>

在本例中,我们映射的是ROWS而不是列。这种方法不支持 ORDER BY,也不支持 SELECT(投影)...

摘要:表,其中 1) 在行中具有与我们的父表相关的值,2) 被某些列区分的表是<map>候选