zoukankan      html  css  js  c++  java
  • [FIM]如何通过Provision Code来向另一张表新增数据(附错误实例)

    最近在做FIM的时候,发现Provisioning的项无法被添加了,然后发现自己在重构的时候,出现了一点儿画蛇添足。

    首先说一下为什么要做Provisioning,原因是这样的,在FIM同步里面,假设有一个数据源,另一个目标数据源,目的是从一个数据源将数据导入到目标数据源中。默认情况下,FIM只处理两边都存在的数据,假设有这样两个数据:

    表名:DB1.Table1

    数据:

    aUser, aUserName, aMobile

    bUser, bUserName, bMobile

    表名:DB2.Table2

    bUser, bUserName1, bMobile1

    cUser, cUserName1, cMobile1

    默认情况下,两张表中,只有INNER JOIN的关系,也就是说bUser被关联了。这样在同步的时候,bUserName将会覆盖bUserName1,bMobile将会覆盖bMobile1,而aUser不会加入到DB2.Table2中。

    而在实际的情况通常是DB1.Table1表代表一个类似HR的系统,新增一个员工的时候,我们希望新来的员工会出现在所有的第三方系统中,因此这个aUser就需要被强加到DB2.Table2中。

    这需要我们为FIM启用Provisoion代码:(Tools->Options->Enable metaverse rules extension + Enable Provisioning Rules Extension)

    image

    然后我们在MVExtension的代码中实现接口void IMVSynchronization.Provision(MVEntry mventry)。

    在我们进行同步的时候,我们需要先将两个数据源的数据都导入(Import)各自的CS中,为了区分不同的数据源的数据,我们为他们分别指定了dataSource的属性,这里我们用一个常量来表示。

    当我们执行哪个MA同步的时候,这个dataSource的值(mventry[“dataSource”])就会是对应MA设置的那个常量,我们也就因此可以在MVExtensions代码中区分不同数据的来源了。

    运行各个MA的时候,各个MA所对应的CS数据会被逐条通过mventry传入MVExtension中进行Provision。也就是说当我们执行DB1.Table1_MA的FULL_SYNC的时候,aUser和bUser都会被导入。当bUser导入的时候,我们可以想象,这个时候,如果我们不做任何事情,就离开这个Provision,按照默认的配置,Join-Rules将被激活,DB1.Table1_MA中的bUser将和DB2.Table2_MA中的bUser建立关联。于是会有一条Join-Rules:

    image

    那么aUser呢?如果不做Provisioning,它将被忽略。这个时候,aUser的ConnectedMAs中只有DB1.Table1_MA,而没有DB2.Table2_MA,因为它还不曾与之关联。

    下面是一段标准的将DB1.Table1_MA中的aUser添加到DB2.Table2_MA的方法,当遇到aUser的mventry的时候,我们取得ConnectedMAs,然后将它添加到DB2.Table2_MA的CS中,并创建Connector。

    private void ProvisioningFIMSys1User1(MVEntry mventry)
    {
        try
        {
            Logger.Get().Write("-----ProvisioningFIMSys1User1 start-----");
            ConnectedMA MA = null;
            if (TryGetMA(mventry, MAs.FIMSys1_User1_MA.NAME, out MA))
            {
                string dn = string.Empty;
                Logger.Get().Write(string.Format("MA.Connectors.Count == {0}", MA.Connectors.Count));
                if (MA.Connectors.Count == 0) // create new one
                {
                    CSEntry csEntry = null;
                    Logger.Get().Write(string.Format("mventry[\"{0}\"].IsPresent = {1}", MVs.Person.Attributes.accountName, mventry[MVs.Person.Attributes.accountName].IsPresent));
                    if (mventry[MVs.Person.Attributes.accountName].IsPresent)
                    {
                        dn = mventry[MVs.Person.Attributes.accountName].StringValue;
                        Logger.Get().Write(string.Format("dn.0 = {0}", dn));
                        csEntry = MA.Connectors.StartNewConnector(MVs.Person.NAME);
                        // create DN for csEntry.
                        csEntry.DN = MA.CreateDN(dn);
                        csEntry.CommitNewConnector();
                        csEntry[MAs.FIMSys1_User1_MA.Attributes.UniqueID].StringValue = mventry[MVs.Person.Attributes.accountName].StringValue;
                        csEntry[MAs.FIMSys1_User1_MA.Attributes.UserName].StringValue = mventry[MVs.Person.Attributes.displayName].StringValue;
                        csEntry[MAs.FIMSys1_User1_MA.Attributes.Mobile].StringValue = mventry[MVs.Person.Attributes.mobile].StringValue;
                        Logger.Get().Write("-----csEntry.CommitNewConnector(); -----");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Logger.Get().Write("Exception:" + ex.ToString());
            throw ex;
        }
        finally
        {
            Logger.Get().Write("-----ProvisioningFIMSys1User1 end-----");
        }
    }
    

    这个TryGetMA是一个用来获取MA的方法:

    public bool TryGetMA(MVEntry mventry, string MAname, out ConnectedMA ma)
    {
        ma = null;
        bool result = false;
        if (mventry == null)
            result = false;
        else
        {
            ma = mventry.ConnectedMAs[MAname];
            Logger.Get().Write("GET MA: " + MAname);
            if (ma == null)
                result = false;
            else
                result = true;
        }
        return result;
    }
    

    下面看看我做了什么蠢事,在之前它是这样写的(不正确):

    public bool TryGetMA(MVEntry mventry, string MAname, out ConnectedMA ma)
    {
        ma = null;
        bool result = false;
        if(mventry == null)
            result = false;
        else
        {
            if (ExistsMA(mventry, MAname))
            {
                ma = mventry.ConnectedMAs[MAname];
                Logger.Get().Write("GET MA: " + MAname);
            }
            if(ma == null)
                result = false;
            else
                result = true;
        }
        return result;
    }
    

    仔细看一下这个ExistsMA:

    private bool ExistsMA(MVEntry mventry, string MAname)
    {
        if (mventry != null && mventry.ConnectedMAs.Count > 0)
        {
            foreach (ConnectedMA ma in mventry.ConnectedMAs)
            {
                if (ma.Name == MAname) return true;
            }
        }
        return false;
    }
    

    倒不是这个方法抛出了异常。而是因为当这个mventry在还没有与该MA建立关联的时候,我就试图去寻找它,当然返回的结果一定是false,于是我永远都无法获得这个MA。

  • 相关阅读:
    PHP技巧通过COM使用ADODB
    PHP开发环境安装配置全攻略
    散列表
    poj Antiprime Sequences
    HDU 2011 菜鸟杯
    UVA The ? 1 ? 2 ? ... ? n = k problem
    poj 3126 Prime Path
    uva 699 The Falling Leaves
    UVA Steps
    poj 1426 Find The Multiple
  • 原文地址:https://www.cnblogs.com/volnet/p/2310785.html
Copyright © 2011-2022 走看看