0
Answered

Problem using Composite Key Relationship

Bob Bradley 8 years ago • updated by anonymous 4 years ago 11

I am trying to configure an instance of a Relational.Composite transformation by following the online guide for this, specifically with the goal of deriving a new DN attribute via a composite key relationship. I was originally trying to find out what the parameter name might be (the equivalent group transformation has a "GroupTarget" parameter) but couldn't find anything (see comment on the link above). However, I since realised that I am probably supposed to be setting the "target" property of the dn element itself ... but now that I am doing this I am getting an erroneous "The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter". I say erroneous because there is no such duplicate declaration.

My suspicion here is that most people have been using the "columnMappings" element with this transformation instead of "dn" and hence this question hasn't come up before - and the example xml appears to include redundant properties InputKey and RelationshipKey, so I am thinking there might be another doco inconsistency here too?

Affected Versions:
Fixed by Version:

Problematic adapter configuration is presently as follows:

        <!-- 008 Meta Tuple Value -->
        <AdapterConfiguration BaseConnectorId="{D801CE82-6D68-444c-B9C4-79D5523B5FC5}"
              AdapterId="{2F7F216B-BE86-4fcf-ACA6-A7D0F6524BC4}"
              AdapterName="Meta Tuple Value Adapter"
              class="metaTupleValue" >
          <dn>
            <dnComponent name="Field" key="ValueLevel2" attributeType="CN" />
            <dnComponent name="Field" key="ValueLevel1" attributeType="OU" />
            <dnComponent name="Field" key="ApplicationName" attributeType="OU" />
            <dnComponent name="Constant" value="MetaTupleValues" attributeType="OU" />
          </dn>
          <adapterEntityTransformationFactory name="ChainList">
            <adapter name="Relational.Composite"
                RelationshipConnectorId="{18F808C6-2430-46ba-9E18-DE6A02F71FF8}">
              <dn
                target="ValueLevel1ID">
                <dnComponent name="Field" key="DisplayName" attributeType="CN" />
                <dnComponent name="Field" key="Category" attributeType="OU" />
                <dnComponent name="Field" key="ApplicationName" attributeType="OU" />
                <dnComponent name="Constant" value="MetaValues" attributeType="OU" />
              </dn>
              <Relationships>
                <Relationship InputKey="ApplicationName" RelationshipKey="ApplicationName" />
                <Relationship InputKey="CategoryLevel1" RelationshipKey="Category" />
                <Relationship InputKey="ValueLevel1" RelationshipKey="DisplayName" />
              </Relationships>
            </adapter>
            <adapter name="Relation.Group.Composite"
                RelationshipConnectorId="{18F808C6-2430-46ba-9E18-DE6A02F71FF8}"
                GroupTarget="ValueLevel2ID">
              <dn>
                <dnComponent name="Field" key="DisplayName" attributeType="CN" />
                <dnComponent name="Field" key="Category" attributeType="OU" />
                <dnComponent name="Field" key="ApplicationName" attributeType="OU" />
                <dnComponent name="Constant" value="MetaValues" attributeType="OU" />
              </dn>
              <Relationships>
                <Relationship InputKey="ApplicationName" RelationshipKey="ApplicationName" />
                <Relationship InputKey="CategoryLevel2" RelationshipKey="Category" />
                <Relationship InputKey="ValueLevel2" RelationshipKey="DisplayName" />
              </Relationships>
            </adapter>
          </adapterEntityTransformationFactory>
          <image>xxx</image>
        </AdapterConfiguration>

Note that if I replace the above Relational.Composite adapter with Relation.Group.Composite and replace the dn "target" property with a "GroupTarget" property of the adapter, the service starts and there is no error ... but I don't want a group transformation for the first of the above two adapters.

Hi Bob,

This is a relational transformation, there is no "group target".

Are you after a group based transformation?

If not, and this is the one you are after, can't you just use the dn generator for the adapter?

Adam - that's what I am trying to do now (use the dn generator), and I'm getting the above exception (figured there was no group target) ... and no, I don't want a group transform

Could you please attached the full exception details (stack trace etc)?

Thanks.

I have been running with the group equivalent Relation.Group.Composite while this investigation is going on, and just altered it to the Relational.Composite and restarted the service (removing the GroupTarget property of the adapter node, and replacing it with a target property of the dn node) and got the following 2 Application Event log entries:

Log Name:      Application
Source:        The following error in Adapters occurred during start of the server: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check you
Date:          21/12/2011 23:32:23
Event ID:      0
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      EDMGT051.construction.enet
Description:
Error occurred in module: Adapters

The following error occurred: 
Unify.Framework.AdapterColumnException: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check your configuration before continuing. ---> System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution contribution)
   --- End of inner exception stack trace ---
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution contribution)
   at Unify.Framework.DistinguishedNameAttributeMapper.AddContributingAdapterTransformation(IAdapterColumnSources contributingDictionary, Func`3 factoryContribution)
   at Unify.Adapters.ExtendedTransformations.EntityCompositeKeyDistinguishedNameRelationMapperValueAdapterFactoryBase.ApplyChangeDetectionColumnInformation(IAdapterColumnSources columnInformation)
   at Unify.Framework.EntityChainAdapterFactory.ApplyChangeDetectionColumnInformation(IAdapterColumnSources columnInformation)
   at Unify.Framework.AdapterEngine.CreateAdapter(IEntityPartitionUpdatableContextFactory entityEngineRepositoryFactory, IConnectorRepository connectorRepository, IAdapterEntityPartitionUpdatableContextFactory adapterEntityPartitionUpdatableContextFactory, IAdapterConfiguration adapterConfiguration)
   at Unify.Framework.AdapterEngine.<>c__DisplayClass10.<CreateCompositeAdapter>b__f(IAdapterConfiguration adapterConfiguration)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Unify.Framework.CompositeAdapter..ctor(IEnumerable`1 adapters, Guid adapterId, String adapterName, Image adapterImage, IAdapterEntityPartitionUpdatableContextFactory adapterContextFactory, IScheduleCollection scheduler)
   at Unify.Framework.AdapterEngine.CreateCompositeAdapter(IEntityPartitionUpdatableContextFactory engineRepositoryFactory, IConnectorRepository connectorRepository, IAdapterEntityPartitionUpdatableContextFactory adapterEntityPartitionUpdatableContextFactory, ICompositeAdapterConfiguration compositeAdapterConfiguration)
   at Unify.Framework.AdapterEngine.<>c__DisplayClass2.<Start>b__1(ICompositeAdapterConfiguration adapterCompositeConfiguration)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Enumerable.<ConcatIterator>d__71`1.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at Unify.Framework.Visitor.Visit[T](IEnumerable`1 visitCollection, Action`2 visitor)
   at Unify.Framework.Visitor.Visit[T](IEnumerable`1 visitCollection, Action`1 visitor)
   at Unify.Framework.AdapterEngine.Start()
   at Unify.Framework.UnifyEngine.Start()
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="The following error in Adapters occurred during start of the server: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check you" />
    <EventID Qualifiers="0">0</EventID>
    <Level>2</Level>
    <Task>0</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2011-12-21T12:32:23.000000000Z" />
    <EventRecordID>362002</EventRecordID>
    <Channel>Application</Channel>
    <Computer>EDMGT051.construction.enet</Computer>
    <Security />
  </System>
  <EventData>
    <Data>Error occurred in module: Adapters

The following error occurred: 
Unify.Framework.AdapterColumnException: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check your configuration before continuing. ---&gt; System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution contribution)
   --- End of inner exception stack trace ---
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution contribution)
   at Unify.Framework.DistinguishedNameAttributeMapper.AddContributingAdapterTransformation(IAdapterColumnSources contributingDictionary, Func`3 factoryContribution)
   at Unify.Adapters.ExtendedTransformations.EntityCompositeKeyDistinguishedNameRelationMapperValueAdapterFactoryBase.ApplyChangeDetectionColumnInformation(IAdapterColumnSources columnInformation)
   at Unify.Framework.EntityChainAdapterFactory.ApplyChangeDetectionColumnInformation(IAdapterColumnSources columnInformation)
   at Unify.Framework.AdapterEngine.CreateAdapter(IEntityPartitionUpdatableContextFactory entityEngineRepositoryFactory, IConnectorRepository connectorRepository, IAdapterEntityPartitionUpdatableContextFactory adapterEntityPartitionUpdatableContextFactory, IAdapterConfiguration adapterConfiguration)
   at Unify.Framework.AdapterEngine.&lt;&gt;c__DisplayClass10.&lt;CreateCompositeAdapter&gt;b__f(IAdapterConfiguration adapterConfiguration)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Unify.Framework.CompositeAdapter..ctor(IEnumerable`1 adapters, Guid adapterId, String adapterName, Image adapterImage, IAdapterEntityPartitionUpdatableContextFactory adapterContextFactory, IScheduleCollection scheduler)
   at Unify.Framework.AdapterEngine.CreateCompositeAdapter(IEntityPartitionUpdatableContextFactory engineRepositoryFactory, IConnectorRepository connectorRepository, IAdapterEntityPartitionUpdatableContextFactory adapterEntityPartitionUpdatableContextFactory, ICompositeAdapterConfiguration compositeAdapterConfiguration)
   at Unify.Framework.AdapterEngine.&lt;&gt;c__DisplayClass2.&lt;Start&gt;b__1(ICompositeAdapterConfiguration adapterCompositeConfiguration)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Enumerable.&lt;ConcatIterator&gt;d__71`1.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at Unify.Framework.Visitor.Visit[T](IEnumerable`1 visitCollection, Action`2 visitor)
   at Unify.Framework.Visitor.Visit[T](IEnumerable`1 visitCollection, Action`1 visitor)
   at Unify.Framework.AdapterEngine.Start()
   at Unify.Framework.UnifyEngine.Start()</Data>
  </EventData>
</Event>
Log Name:      Application
Source:        UNIFY Identity Broker v3.0 service
Date:          21/12/2011 23:32:24
Event ID:      0
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      EDMGT051.construction.enet
Description:
Service cannot be started. Unify.Framework.UnifyServerStartException: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check your configuration before continuing. ---> Unify.Framework.AdapterColumnException: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check your configuration before continuing. ---> System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution contribution)
   --- End of inner exception stack trace ---
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution ...
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="UNIFY Identity Broker v3.0 service" />
    <EventID Qualifiers="0">0</EventID>
    <Level>2</Level>
    <Task>0</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2011-12-21T12:32:24.000000000Z" />
    <EventRecordID>362003</EventRecordID>
    <Channel>Application</Channel>
    <Computer>EDMGT051.construction.enet</Computer>
    <Security />
  </System>
  <EventData>
    <Data>Service cannot be started. Unify.Framework.UnifyServerStartException: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check your configuration before continuing. ---&gt; Unify.Framework.AdapterColumnException: The column ValueLevel1ID is a pre-existing column in adapter Meta Tuple Value Adapter (2f7f216b-be86-4fcf-aca6-a7d0f6524bc4).  Please check your configuration before continuing. ---&gt; System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution contribution)
   --- End of inner exception stack trace ---
   at Unify.Framework.AdapterColumnSources.Add(IAdapterEntityTransformationFactoryContribution ...</Data>
  </EventData>
</Event>

How can you be running with the Relation.Group.Composite when that is not what you desire? What is it that you are trying to do?

I can see an issue in the code, but I would like to schedule a fix for it, as the change involves quite a large design change.

Can you work around the issue with a columnMappings attribute instead of the dn attribute, and use an adapter level dn generator instead?

Thanks.

Adam - my requirement for the above adapter is a single value reference attribute and a multi-value reference attribute. It works if I treat them as 2 multi-value reference attributes, but the first will map to a single value reference attribute in the metaverse and what I want (in the case of bad data) is a "discovery error" not a "sync error" (i.e. the discovery error will point to either bad data or some other database problem which if allowed through to the sync engine could be misinterpreted).

Anyhow ... I am guessing there's more than one way to do what I want to do, and am happy to use your work-around once I get my head around what you mean by this (presumably in a chain-list).

I'm still not sure how you can be working with a multi-value reference value instead of a single value. The single reference works using a one-to-one relationship, whereas the multi-value is generated on a one-to-many relationship.

Let me know how you go.

Thanks.

It "works" because a one-to-one relationship can always be considered a special case of a one-to-many relationship, that's all. In my case I can build with a one-to-many relationship because it generates a DN for me ... and so long as I don't happen to get multiple values in this property I can treat it as a single value and don't get any flow errors. However I don't want to leave it this way, and will try your suggested work-around.

Resolved issue with multiple contributions to a key. (v3.0.7)

Have yet to try this myself, but closing anyhow. If there is a problem with the latest fix I will re-open.