public async Task <AccountHierarchy> AddNode(AccountHierarchy entity, bool autoCommit = true) { var sponsor = await _dbContext.AccountHierarchies .Include(a => a.Children).FirstOrDefaultAsync(a => a.Id == entity.UplinkId); if (sponsor.Children.Count == 0) { entity.ParentId = sponsor.Id; entity.Leg = sponsor.PlacementPreference == 2 ? 2 : 1; } else { Stopwatch sw = Stopwatch.StartNew(); var sponsorTree = await _dbContext.AccountHierarchies .OrderBy(a => a.LevelPath.Length) .ThenBy(a => a.LevelPath) .Where(a => a.LevelPath.StartsWith(sponsor.LevelPath)) .AsNoTracking() .ToListAsync(); System.Console.WriteLine("Finding parent for entity " + entity.Name); var parent = await Task.Run(() => FindAvailableNodeInLoop(sponsorTree)); System.Console.WriteLine($"Found parent {parent.Name} for entity {entity.Name}, took {sw.ElapsedMilliseconds} ms"); entity.ParentId = parent.Id; entity.Leg = parent.PlacementPreference; } var created = await this.AddToParent(entity, entity.ParentId, autoCommit); return(created); }
private async Task <AccountHierarchy> AddToParent(AccountHierarchy entity, long?parentId, bool autoCommit = true) { if (!parentId.HasValue) { SqlHierarchyId parentLevel = SqlHierarchyId.GetRoot(); entity.ParentId = null; entity.UplinkId = null; entity.LevelPath = parentLevel.ToString(); } else { var parent = await _dbContext.AccountHierarchies.Where(x => x.Id == parentId) .Include(x => x.Children) .FirstOrDefaultAsync(); SqlHierarchyId parentLevel = SqlHierarchyId.Parse(parent.LevelPath); var lastSibling = parent.Children.OrderByDescending(x => x.LevelPath).FirstOrDefault(); string levelPath = null; if (entity.Leg == 2) { if (lastSibling == null) { levelPath = parent.LevelPath + "2/"; } else { SqlHierarchyId newLevel = parentLevel.GetDescendant(SqlHierarchyId.Parse(lastSibling.LevelPath), SqlHierarchyId.Null); levelPath = newLevel.ToString(); } } else if (entity.Leg == 1) // in any other case - put it on the left { if (lastSibling == null) { levelPath = parent.LevelPath + "1/"; } else { SqlHierarchyId newLevel = parentLevel.GetDescendant(SqlHierarchyId.Null, SqlHierarchyId.Parse(lastSibling.LevelPath)); levelPath = newLevel.ToString(); } } else { throw new ArgumentOutOfRangeException("Leg", "Invalid value for leg: " + entity.Leg); } entity.LevelPath = levelPath; entity.ParentId = parentId; } var result = (await _dbContext.AccountHierarchies.AddAsync(entity)).Entity; if (autoCommit) { await _dbContext.SaveChangesAsync(); } return(result); }