Master Data Services : Copie / Import / Export des Business Rules (Inter modèles)

updated article (Oct 2011)

(code refactored)

Hi All,

One other missing feature of MDS is Import / Export / Copy Business rules from a model to another (or copy business rules to the same model)

my code is still in beta, but it is already (partially) working.

you can find it on my « MDS Manager » tool on codeplex:

http://mdsmanager.codeplex.com


Get business rules from modelId, quite easy with service client method « business rules get », returns a business rule set

 public BusinessRules GetBusinessRules(string fileName)
        {
            BusinessRules brs = null;
            Stream str = null;
            try
            {

                if (File.Exists(fileName))
                {
                    str = new FileStream(@fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

                    if (str == null)
                    {
                        throw new BusinessRulesException("error while opening file!");
                    }

                    XmlSerializer xs = new XmlSerializer(typeof(BusinessRules));
                    // Load the object saved above by using the Deserialize function
                     brs = (BusinessRules)xs.Deserialize(str);

                }
                else
                {
                    throw new BusinessRulesException("Cannot find specified file!");
                }

                return brs;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {

                // Cleanup                 if (str != null)
                    str.Close();

            }

        }
then we export business rules to a XML file
note:
//this is needed to avoid a serialization error (more info on http://www.johnsoer.com/blog/?p=125 ) :
 //XmlSerializer xs = new XmlSerializer(typeof(BusinessRules), new Type[] { typeof(BRAttributeValueArgument),typeof(BRBlankArgument)
   //                                                                                     ,typeof(BRDomainBasedAttributeArgument)});
here is the export method :
 public void ExportBusinessRules(string exportFileName, BusinessRules brs)
        {
            TextWriter WriteFileStream = null;
            try
            {

                //new type needed to avoir error because serialization of an inherited class                 XmlSerializer xs = new XmlSerializer(typeof(BusinessRules), new Type[] { typeof(Common.ServiceReference1.BRAttributeValueArgument) });
//update oct 2011!
//new type needed to avoir error because serialization of an inherited class

               XmlSerializer xs = new XmlSerializer(typeof(BusinessRules), new Type[] { typeof(BRAttributeValueArgument),typeof(BRBlankArgument)
                                                                                        ,typeof(BRDomainBasedAttributeArgument)});
              // Create a new file stream to write the serialized object to a file                 WriteFileStream = new StreamWriter(@exportFileName);
                xs.Serialize(WriteFileStream, brs);

               //custom exception class , but not required              throw new BusinessRulesException("Business Rules successfully exported to file " + exportFileName);

            }
            catch (Exception exc)
            {
                throw exc;
            }
            finally
            {
               // Cleanup                 if (WriteFileStream != null)
                    WriteFileStream.Close();
            }
        }

then we would like to import this XML file to another model:
here is the method to get business rules set from a previously exported XML file :
  public BusinessRules GetBusinessRules(string fileName)
        {
            BusinessRules brs = null;
            Stream str = null;
            try
            {

                if (File.Exists(fileName))
                {
                    str = new FileStream(@fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

                    if (str == null)
                    {
                        throw new BusinessRulesException("error while opening file!");
                    }

                    XmlSerializer xs = new XmlSerializer(typeof(BusinessRules));
                   // Load the object saved above by using the Deserialize function                    brs = (BusinessRules)xs.Deserialize(str);

                }
                else
                {
                    throw new BusinessRulesException("Cannot find specified file!");
                }

                return brs;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {

              // Cleanup 
          if (str != null)
                    str.Close();

            }

        }

//then we can get the source modelID
 sourceModelId =brs.BusinessRulesMember.First().Identifier.ModelId as Identifier;
// and then clone business rule set with updated modelId:
//brs is the business rule set
//sourceModelId is the source Model Identifier (taken above from the Rules set from the XML file)
//target ModelId is the model Identifier for the model we want to import back the B. rules to
CloneBusinessRules(brs,sourceModelId, targetModelId));
Here is the CloneBusinessRules Method:
public string CloneBusinessRules(BusinessRules brs, Identifier SourceModelId, Identifier targetModelId)
        {

            OperationResult or = null;
            //instanciate new BR members
            try
            {
                int cptMissingEntity = 0;
                StringBuilder sb = new StringBuilder("these business rule related entities does not exists in target model:");
                sb.AppendLine();
                BusinessRules newBRS = new BusinessRules();
                foreach (BusinessRule br in brs.BusinessRulesMember)
                {
                    Identifier EntityId = null;
                    //this is used to get the target entity Id with matching its name 
                    using (ServiceClient c = new ServiceClientWrapper().CreateServiceClient())
                    {
                        EntityId = GetEntityIdFromName(c, c.Endpoint.Address.Uri.OriginalString, targetModelId, br.Identifier.EntityId.Name);

                    }
                    if (EntityId != null)
                    {
                        newBRS.BusinessRulesMember = new Collection<BusinessRule>();

                        //create a new business rule based on the source one, and applying on it the target identifiers and names 
                        BusinessRule newBR = BusinessRuleInstanciate(Guid.NewGuid(), br.Identifier.Name, targetModelId.Name, br.Identifier.EntityId.Name,
                            br.Identifier.MemberType, br.Priority, br.BRActions, br.Identifier.InternalId, br.RuleActionText, br.RuleConditionText);
                        //some required parameters to instanciate below:

                        //instanciate BRActions
                        newBRS.BRActions = BRActionsInstanciate(brs.BRActions, newBR.Identifier);
                        //instanciate BRConditions
                        newBRS.BRConditions = BRConditionsInstanciate(brs.BRConditions, newBR.Identifier);
                        //instanciate BRConditionTreeNodes
                        newBRS.BRConditionTreeNodes = BRConditionTreeNodesInstanciate(brs.BRConditionTreeNodes, newBR.Identifier);
                        newBRS.BusinessRulesMember.Add(newBR);
                    }
                    else
                    {
                        sb.AppendLine(br.Identifier.EntityId.Name);
                        cptMissingEntity++;
                        //these business rule related entities do not exist in target model
                    }
                    //then we clone modified BRSet
                    using (ServiceClient c = new ServiceClientWrapper().CreateServiceClient())
                    {

                        or = c.BusinessRulesClone(new International(), newBRS);
                        string err = Tools.HandleErrors(or);
                        if (!string.IsNullOrEmpty(err))
                        {
                            throw new Exception(err);
                        }
                    }
                    if (cptMissingEntity == 0)
                    {
                        sb = new StringBuilder();
                    }
                }

                return sb.ToString();
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }

update oct 2011 code for BRActionsInstanciate, BRConditionsInstanciate,BRConditionTreeNodesInstanciate

 private Collection<BRConditionTreeNode> BRConditionTreeNodesInstanciate(Collection<BRConditionTreeNode> BRConditionTreeNodes, MemberTypeContextIdentifier BRId)
        {

            try
            {
                //Add BRConditionTreeNode to BRConditionTreeNode Collection

                Collection<BRConditionTreeNode> newBRConditionTreeNodes = new Collection<BRConditionTreeNode>();

                foreach (BRConditionTreeNode brctn in BRConditionTreeNodes)
                {
                    BRConditionTreeNode BRConditionTreeNodeItem = new BRConditionTreeNode();
                    //Add Attribute and Action type to the collection
                    BRConditionTreeNodeItem.BRConditions = BRConditionsInstanciate(brctn.BRConditions, BRId);
                    BRConditionTreeNodeItem.BusinessRuleId = BRId;
                    BRConditionTreeNodeItem.ConditionTreeChildNodes = brctn.ConditionTreeChildNodes;
                    BRConditionTreeNodeItem.ConditionTreeParentNode = brctn.ConditionTreeParentNode;
                    BRConditionTreeNodeItem.LogicalOperator = brctn.LogicalOperator;
                    BRConditionTreeNodeItem.Identifier = new Identifier() { Name = brctn.Identifier.Name, Id = Guid.NewGuid() };

                    //All Action and Condition Items must have a sequence greater that zero
                    BRConditionTreeNodeItem.Sequence = brctn.Sequence;
                    newBRConditionTreeNodes.Add(BRConditionTreeNodeItem);
                }
                return newBRConditionTreeNodes;
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }

        private Collection<BRAction> BRActionsInstanciate(Collection<BRAction> BRActions, MemberTypeContextIdentifier BRId)
        {

            try
            {
                //Add Action to Action Collection

                Collection<BRAction> newBRActions = new Collection<BRAction>();

                foreach (BRAction bra in BRActions)
                {
                    BRAction BRActionItem = new BRAction() { Identifier = new Identifier() { Id = Guid.NewGuid(), Name = bra.Identifier.Name }, BusinessRuleId = BRId };
                    //Add Attribute and Action type to the collection
                    BRActionItem.PrefixArgument = new BRAttributeArgument();
                    BRActionItem.PrefixArgument.PropertyName = bra.PrefixArgument.PropertyName;
                    BRActionItem.PrefixArgument.AttributeId = new Identifier();
                    BRActionItem.PrefixArgument.AttributeId.Id = Guid.NewGuid();
                    BRActionItem.PrefixArgument.AttributeId.Name = bra.PrefixArgument.AttributeId.Name;
                    BRActionItem.Operator = bra.Operator;
                    var colBRffa = new Collection<object>();
                    foreach (var brffa in bra.PostfixArguments)
                    {
                        BRBlankArgument BRba = brffa as BRBlankArgument;
                        BRFreeformArgument BRffa = brffa as BRFreeformArgument;
                        if (BRba != null)
                        {
                            colBRffa.Add(new BRBlankArgument() { Identifier = new Identifier() { Id = Guid.NewGuid(), Name = BRba.Identifier.Name }, PropertyName = BRba.PropertyName });

                        }
                        else
                        {
                            if (BRffa != null)
                            {
                                colBRffa.Add(new BRFreeformArgument() { Identifier = new Identifier() { Id = Guid.NewGuid(), Name = BRffa.Identifier.Name }, Value = BRffa.Value, PropertyName = BRffa.PropertyName });

                            }
                        }
                    }
                    BRActionItem.PostfixArguments = colBRffa;
                    BRActionItem.Text = bra.Text;

                    //All Action and Condition Items must have a sequence greater that zero
                    BRActionItem.Sequence = bra.Sequence;
                    newBRActions.Add(BRActionItem);
                }
                return newBRActions;
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }
        public Collection<BRCondition> BRConditionsInstanciate(Collection<BRCondition> BRconditions, MemberTypeContextIdentifier BRId)
        {

            try
            {
                //Add Action to Action Collection

                Collection<BRCondition> newBRconditions = new Collection<BRCondition>();
                BRCondition BRConditionItem = new BRCondition();

                foreach (BRCondition brc in BRconditions)
                {
                    //Add Attribute and Action type to the collection
                    BRConditionItem.BusinessRuleId = BRId;

                    BRConditionItem.ConditionTreeNodeId = new Identifier() { Name = brc.ConditionTreeNodeId.Name };
                    BRConditionItem.Identifier = new Identifier() { Id = Guid.NewGuid(), Name = brc.Identifier.Name };
                    BRConditionItem.Operator = brc.Operator;
                    BRConditionItem.PrefixArgument = brc.PrefixArgument;
                    BRConditionItem.PostfixArguments = brc.PostfixArguments;
                    //All Action and Condition Items must have a sequence greater that zero
                    BRConditionItem.Sequence = brc.Sequence;
                    BRConditionItem.Text = brc.Text;
                    newBRconditions.Add(BRConditionItem);
                }
                return newBRconditions;
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }
Taggé , , , , , , , , , .Mettre en favori le Permaliens.

A propos Xavier

7 years+ .net consulting

2 réponses à Master Data Services : Copie / Import / Export des Business Rules (Inter modèles)

  1. Miron dit :

    Posted a few weeks ago some methods that could help.

    In my experience attempt to save a business rule with all properties and collections failed. I had to create business rule, could think of it as header. This is how you would create business rule in UI, too. And than add one section at a time actions and conditions. I have also added an initial call to get all entities interested in, cache those and lookup in collection using link, which speeds up creating business rules quite a bit. Please let me know how I can contact you, if you are interested. Thank you, Miron.

  2. Scott Pedersen dit :

    Great work, this will come in very useful for business rule changes that need to be migrated between environments.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha * Time limit is exhausted. Please reload CAPTCHA.