如何使用更新上下文消息获取更新字段

时间:2018-12-21 07:11:15

标签: c# plugins dynamics-crm

我不知道更新最大值后如何获取最大金额。

enter image description here 当我创建新的最高金额时,0.01将自动更新下一个最低金额。

enter image description here 当我更新最高金额时,最低金额不会更新为新的最低金额25,000.01

if (context.MessageName == "Create") {
    Guid RebateLevelsId = new Guid();
    RebateLevelsId = targetEntity.Id;

    if (targetEntity.Attributes.Contains("new_usagerebate")) {
        EntityReference usageRebateEnt = (EntityReference) targetEntity.Attributes["new_usagerebate"];
        Guid usageRebateId = usageRebateEnt.Id;

        EntityCollection rebateLevelEnt = GetEntityCollectionRebateLevel(service, "new_rebatelevels", "new_usagerebate", usageRebateId, new ColumnSet(true));

        Entity rebateLevelEntity = new Entity("new_rebatelevels", RebateLevelsId);
        attributes A = new attributes();

        if (rebateLevelEnt.Entities.Count > 0) {
            for (int i = 0; i < rebateLevelEnt.Entities.Count; i++) {
                if (i == rebateLevelEnt.Entities.Count - 1) {
                    A.level = i + 1;
                }
                if (i == rebateLevelEnt.Entities.Count - 2) {
                    A.Max_Amount = rebateLevelEnt.Entities[i].GetAttributeValue < decimal > ("new_maxamount");
                }
            }

            rebateLevelEntity["new_level"] = A.level.ToString();
            rebateLevelEntity["new_minamount"] = A.Max_Amount + 0.01 m;
            service.Update(rebateLevelEntity);
        } else {
            rebateLevelEntity["new_level"] = 1. ToString();
            service.Update(rebateLevelEntity);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

我对这个问题进行了思考,并编写了一个示例说明如何处理该问题。

我一直在寻找一种健壮的解决方案,该解决方案可以同时调整我们正在创建或更新的层次之上和之下的水平。此解决方案涵盖的案例包括:

  1. 从0级记录开始,然后添加
  2. 最低水平可能低于先前水平的最高水平-在这种情况下,我们将调整先前水平的最高水平。
  3. Min可能低于先前级别的min-在这种情况下,我们抛出异常。
  4. 最大值可能高于下一级的最小值-在这种情况下,我们会调整下一级的最小值。
  5. 最大值可能高于下一级的最大值-在这种情况下,我们将引发异常。
  6. 最小值可能低于上一级的最大值,最大值可能高于下一级的最小值,在这种情况下,我们会同时调整上一级和下一级。
  7. 最小值可能低于上一级的最小值,最大值可能高于下一级的最大值,在这种情况下,我们将抛出一个包含有关两个问题的信息的异常。
  8. 具有三个以上级别的可能性。
  9. 处理创建和更新事件。

缺少的一件事是确保用户不跳过级别的逻辑。另一个是处理删除操作。

我没有在D365系统中创建实体,而是将其构建为在控制台应用程序中与虚拟数据一起运行,并且IOrganizationService调用已注释掉。但是,它使用EntityCollectionEntity类,因此您应该能够轻松地插入实时数据。

我采用了一种面向对象的方法。 Level类最初是作为包装器来公开new_rebatelevel's数据的,而不必不断使用GetAttributeValue<>。它成长为一个健壮的类,承担着很大的负担。

target代表已创建或更新的级别。

主要内容:

class Program
{
    static void Main(string[] args)
    {
        var app = new App_CalcMinMax();
        app.Run();
        if (System.Diagnostics.Debugger.IsAttached)
        {
            Console.WriteLine("\nPress <Enter> to continue...");
            Console.ReadLine();                
        }
    }
}

和“应用”:

using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class App_CalcMinMax 
{
    public void Run()
    {            
        var rebates = new UsageRebate(toCollection(new List<Entity>())); //start with an empty list
        //process various level create and update events
        //and display the results of each event
        //.Process() takes the level #, the min, and the max
        rebates.Process(1, 0, 10000);
        rebates.Process(2, 11000.01m, 20000);
        rebates.Process(3, 21000.01m, 30000);          
        rebates.Process(1, 0, 9000);            
        rebates.Process(2, 10000, 15000);            
        rebates.Process(3, 17000, 35000);
        rebates.Process(3, 12000, 24000);
        rebates.Process(2, 8000, 20000);
        rebates.Process(1, 0, 25000);
        rebates.Process(2, 14000, 19000);
    }

    private class Level
    {
        private Entity e;
        private Level lower;
        private Level upper;
        public int Num => e.GetAttributeValue<int>("new_level");
        public decimal Min => e.GetAttributeValue<Money>("new_minamount").Value;
        public decimal Max => e.GetAttributeValue<Money>("new_maxamount").Value;
        public bool IsValidLower => lower == null ? true : Min > lower.Min;
        public bool IsValidUpper => upper == null ? true : Max < upper.Max;
        public bool IsValid => IsValidLower && IsValidUpper;
        public bool AdjustLower => lower == null ? false : Min - 0.01m != lower.Max;
        public bool AdjustUpper => upper == null ? false : Max + 0.01m != upper.Min;

        public Level(Entity e)
        {
            this.e = e;
        }
        public void ValidateLower(Level lower)
        {
            this.lower = lower;
        }
        public void ValidateUpper(Level upper)
        {
            this.upper = upper;
        }
        public void SetMin(decimal value, IOrganizationService service = null)
        {
            e["new_minamount"] = new Money(value);
            //service.Update(e);
        }
        public void SetMax(decimal value, IOrganizationService service = null)
        {
            e["new_maxamount"] = new Money(value);
            //service.Update(e)
        }
        public override string ToString()
        {
            return $" Level: {Num}\tmin: { Min.ToString("N2"),9}\tmax: { Max.ToString("N2"),9}";
        }
    }

    private class UsageRebate
    {
        private IOrganizationService service;
        private EntityCollection ec;
        private IEnumerable<int> levelNums => Levels.Select(l => l.Num);
        public IEnumerable<Entity> Entities => ec.Entities;
        public IEnumerable<Level> Levels => Entities.Select(e => new Level(e));
        public UsageRebate(EntityCollection ec, IOrganizationService service = null)
        {
            this.ec = ec;
            this.service = service;
        }

        public void Process(int num, decimal min, decimal max)
        {
            var target = toEntity(num, min, max);
            var level = new Level(target);                
            Level prior = null;
            Level next = null;
            Console.WriteLine($"Target: {level.ToString()}");

            if (tryGetLevel(level.Num-1,out prior))
            {
                level.ValidateLower(prior);
            }

            if (tryGetLevel(level.Num + 1, out next))
            {
                level.ValidateUpper(next);
            }

            if (level.IsValid)
            {
                if (exists(level.Num))
                {
                    update(target);
                }
                else
                {
                    add(target);
                }
                if (level.AdjustLower)
                {
                    prior.SetMax(level.Min - 0.01m);
                }
                if (level.AdjustUpper)
                {
                    next.SetMin(level.Max + 0.01m);
                }
            }
            else
            {
                string message = "Exception: ";
                if (!level.IsValidLower)
                {
                    message += $"Level {level.Num} Min is less than Level {prior.Num} Min\n";
                }
                if (!level.IsValidUpper)
                {
                    message += $"Level {level.Num} Max exceeds Level {next.Num} Max";                        
                }
                Console.WriteLine(message);
                //throw new Exception(message);
            }

            Console.WriteLine($"Results:\n{ToString()}");
        }

        private bool tryGetLevel(int num, out Level level)
        {
            var ex = exists(num);
            level = ex ? get(num) : null;                
            return ex;
        }

        private void add(Entity entity)
        {
            ec.Entities.Add(entity);
            //service.Create(entity);
        }

        private void update(Entity entity)
        {
            var e = get(entity);
            e["new_minamount"] = entity["new_minamount"];
            e["new_maxamount"] = entity["new_maxamount"];
            //service.Update(entity);
        }

        private bool exists(int num)
        {
            return levelNums.Contains(num);
        }

        private Level get(int num)
        {
            return Levels.Where(l => l.Num == num).Single();
        }

        private Entity get(Entity entity)
        {
            return Entities.Where(e => new Level(e).Num == new Level(entity).Num).Single();
        }

        private Entity toEntity(int level, decimal min, decimal max)
        {
            return new Entity
            {
                LogicalName = "new_rebatelevel",
                Id = Guid.NewGuid(),
                Attributes =
                {
                    new KeyValuePair<string, object>("new_level", level),
                    new KeyValuePair<string, object>("new_minamount", new Money(min)),
                    new KeyValuePair<string, object>("new_maxamount", new Money(max))
                }
            };
        }

        public override string ToString()
        {
            var sb = new StringBuilder();
            Levels.ToList().ForEach(l => sb.AppendLine(l.ToString()));
            return sb.ToString();
        }
    }

    private EntityCollection toCollection(List<Entity> list)
    {
        var ec = new EntityCollection();
        ec.EntityName = "new_rebatelevel";
        ec.Entities.AddRange(list);
        return ec;
    }
}

输出:


目标:级别:1分钟:0.00最大值:10,000.00
结果:
 级别:1分钟:0.00最大值:10,000.00

目标:级别:2分钟:11,000.01最大:20,000.00
结果:
 级别:1分钟:0.00最大:11,000.00
 级别:2分钟:11,000.01最大:20,000.00

目标:等级:3分钟:21,000.01最高:30,000.00
结果:
 级别:1分钟:0.00最大:11,000.00
 等级:2分钟:11,000.01最大:21,000.00
 级别:3分钟:21,000.01最大值:30,000.00

目标:等级:1分钟:0.00最高:9,000.00
结果:
 级别:1分钟:0.00最大:9,000.00
 等级:2分钟:9,000.01最大:21,000.00
 级别:3分钟:21,000.01最大值:30,000.00

目标:等级:2分钟:10,000.00最大值:15,000.00
结果:
 等级:1分钟:0.00最大:9,999.99
 级别:2分钟:10,000.00最大:15,000.00
 水平:3分钟:15,000.01最大:30,000.00

目标:等级:3分钟:17,000.00最大值:35,000.00
结果:
 等级:1分钟:0.00最大:9,999.99
 级别:2分钟:10,000.00最大:16,999.99
 级别:3分钟:17,000.00最大:35,000.00

目标:等级:3分钟:12,000.00最大值:24,000.00
结果:
 等级:1分钟:0.00最大:9,999.99
 级别:2分钟:10,000.00最大:11,999.99
 级别:3分钟:12,000.00最大:24,000.00

目标:等级:2分钟:8,000.00最大值:20,000.00
结果:
 等级:1分钟:0.00最大:7,999.99
 级别:2分钟:8,000.00最大:20,000.00
 级别:3分钟:20,000.01最大值:24,000.00

目标:等级:1分钟:0.00最高:25,000.00
例外:1级最大超出2级最大
结果:
 等级:1分钟:0.00最大:7,999.99
 级别:2分钟:8,000.00最大:20,000.00
 级别:3分钟:20,000.01最大值:24,000.00

目标:等级:2分钟:14,000.00最大值:19,000.00
结果:
 等级:1分钟:0.00最大:13,999.99
 级别:2分钟:14,000.00最大:19,000.00
 级别:3分钟:19,000.01最大:24,000.00

按Enter继续...