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

时间:2014-11-17 22:32:36

标签: c# nhibernate dynamic fluent-nhibernate

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

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那里得到了我的能力:

Support dynamic fields with NHibernate and .NET 4.0

现在,我的模特。

EmailIndicator

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

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

如何使用经典的NHibernate XML映射或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?

以下是一些有趣的文章:

1 个答案:

答案 0 :(得分:1)

我试图将NHibernate动态映射的可能性放在一起:

NHibernate Dynamic mapping

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

予。 IDictionary

首先是客户的非常常见/标准表:

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

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

// [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。事实上,我们可以使用任何(SELECT - Projections - see this custom ResultTransformer working with <dynamic-component>,WHERE ...)

但必须有标准表,其中属性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>

的候选者