[This is preliminary documentation and is subject to change.]

Get this BusinessProcess relations

Namespace:  Firefly.Box
Assembly:  Firefly.Box (in Firefly.Box.dll) Version: 3.4.23.6473 (3.4.23.6473)

Syntax

C#
public RelationCollection Relations { get; }
Visual Basic (Declaration)
Public ReadOnly Property Relations As RelationCollection
Visual C++
public:
property RelationCollection^ Relations {
	RelationCollection^ get ();
}

Remarks

Relations are usually used to retrieve data from lookup entities.
Every relation that is add to the BusinessProcess's Relations property will be part of the reevaluation engine.
Relations Cache - To improve performance, whenever a is required by the relation, and that row was already used in other rows of this relation, it will be fetched from a cache, if all the following rules are met:
  • The Cached property of the relation's Entity is set to true,
  • The filter of the relation points to a unique row. The uniqueness is defined by the Entity's PrimaryKeyColumns property collection, or if it matches a Sort that is part of the Entity's Indexes property collection, that it's Unique property is set to true.
  • Such a row was already found in the relation, on previous rows

To find out more about the reevaluation engine, see Columns property.

Examples

Fetching rows with relations
This example is in the form of Unit Tests. It references the NUnit framework. This framework can be downloaded from www.NUnit.org. For more information about unit testing visit: www.NUnit.org.
This example is based on test data. The code for the entities included in this test data can be found in the documentation of Entity
CopyC#
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Firefly.Box;
using Firefly.Box.Testing;

namespace TestFirefly.Box.Documentation
{
    [TestFixture]
    public class FetchingRowsWithRelations
    {
        [Test]
        public void UsingRelationForALookupTable()
        {
            var employees = new Pubs.Employees();
            var jobs = new Pubs.Jobs();
            employees.InitializeWithTestData();
            jobs.InitializeWithTestData();

            var bp = new BusinessProcess
            {
                From = employees
            };
            bp.Relations.Add(jobs, jobs.Id.IsEqualTo(employees.JobId));
            string namesAndJobs = "";
            bp.ForEachRow(() =>
            {
                namesAndJobs += employees.LastName.Value.TrimEnd() + " - " +
                                jobs.Description.Value.TrimEnd() + "\n";
                if (bp.Counter == 5)
                    bp.Exit();
            });
            namesAndJobs.ShouldBe("Cruz - Productions Manager\n" +
                "Devon - Business Operations Manager\n" +
                "Roulet - Managing Editor\n" +
                "Domingues - Public Relations Manager\n" +
                "Hernadez - Publisher\n");
        }
        [Test]
        public void UsingRelationToFetchTheTopMostRow()
        {
            var jobs = new Pubs.Jobs();
            var employees = new Pubs.Employees();
            jobs.InitializeWithTestData();
            employees.InitializeWithTestData();

            var bp = new BusinessProcess()
            {
                From = jobs
            };
            //A relation that gets the employee with the highest joblevel in the matching job
            bp.Relations.Add(employees, employees.JobId.IsEqualTo(jobs.Id),
                new Sort(employees.JobLevel)).OrderBy.Reversed = true;

            string jobsAndEmployeesWithMaxLevel = "";

            bp.ForEachRow(() =>
            {
                jobsAndEmployeesWithMaxLevel += jobs.Description.ToString().TrimEnd() + " - " +
                                                employees.LastName.ToString().TrimEnd() + "\n";
            });
            jobsAndEmployeesWithMaxLevel.ShouldBe(
                "New Hire - Job not specified - \n" +
                "Chief Executive Officer - Cramer\n" +
                "Business Operations Manager - Devon\n" +
                "Chief Financial Officier - Chang\n" +
                "Publisher - Pontes\n" +
                "Managing Editor - Karttunen\n" +
                "Marketing Manager - Ibsen\n" +
                "Public Relations Manager - Saveley\n" +
                "Acquisitions Manager - Jablonski\n" +
                "Productions Manager - Sommer\n" +
                "Operations Manager - Mendel\n" +
                "Editor - Snyder\n" +
                "Sales Representative - O'Rourke\n" +
                "Designer - Josephs\n");
        }

    }
}

Examples

Deferent Relation Types
This example is in the form of Unit Tests. It references the NUnit framework. This framework can be downloaded from www.NUnit.org. For more information about unit testing visit: www.NUnit.org.
This example is based on test data. The code for the entities included in this test data can be found in the documentation of Entity
CopyC#
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Firefly.Box;
using Firefly.Box.Testing;

namespace TestFirefly.Box.Documentation
{
    [TestFixture]
    public class RelationsTypes
    {
        [Test]
        public void Find()
        {
            var employees = new Pubs.Employees();
            var jobs = new Pubs.Jobs();
            employees.InitializeWithTestData();
            jobs.InitializeWithTestData();
            DeleteJobBusinessOperationsManager();

            var bp = new BusinessProcess
            {
                From = employees
            };
            bp.Relations.Add(jobs, RelationType.Find,//The default Relation Type
                jobs.Id.IsEqualTo(employees.JobId));
            string namesAndJobs = "";
            bp.ForEachRow(() =>
            {
                namesAndJobs += employees.LastName.Value.TrimEnd() + " - " +
                                jobs.Description.Value.TrimEnd() + "\n";
                if (bp.Counter == 5)
                    bp.Exit();
            });
            namesAndJobs.ShouldBe("Cruz - Productions Manager\n" +
                "Devon - \n" +//This row in the job entity was not found
                "Roulet - Managing Editor\n" +
                "Domingues - Public Relations Manager\n" +
                "Hernadez - Publisher\n");
        }
        [Test]
        public void Insert()
        {
            var jobs = new Pubs.Jobs();
            jobs.InitializeWithTestData();
            jobs.CountRows().ShouldBe(14);

            var bp = new BusinessProcess();
            bp.Relations.Add(jobs, RelationType.Insert);
            bp.ForFirstRow(() =>
                               {
                                   //Settings the value for the new relation
                                   jobs.Id.Value = 15;
                                   jobs.Description.Value = "Software Developer";
                               });
            jobs.CountRows().ShouldBe(15);//Now there are 15 jobs, as the 15th job was inserted
        }
        [Test]
        public void InsertIfNotFound()
        {
            var employees = new Pubs.Employees();
            var jobs = new Pubs.Jobs();
            employees.InitializeWithTestData();
            jobs.Truncate();//Truncating the jobs table, so it'll be 
            //recreated using InsertIfNotFound

            string employeeAndJobs = "";
            var bp = new BusinessProcess();
            bp.From = employees;
            var relationToJobs = bp.Relations.Add(jobs, RelationType.InsertIfNotFound,
                             jobs.Id.IsEqualTo(employees.JobId));

            bp.ForEachRow(() =>
                              {
                                  if (!relationToJobs.RowFound)
                                  {
                                      jobs.Id.Value = employees.JobId;
                                      jobs.Description.Value = "Job " + jobs.Id;
                                  }
                                  employeeAndJobs += employees.LastName.ToString().TrimEnd()
                                      + " job "
                                      + employees.JobId.ToString().Trim() + " " +
                                      (relationToJobs.RowFound ? "Exists" : "Doesn't Exist") + "\n";
                                  if (bp.Counter == 15)
                                      bp.Exit();
                              });
            employeeAndJobs.ShouldBe(
                "Cruz job 10 Doesn't Exist\n" + //At this time job 10 doesn't exist
                "Devon job 3 Doesn't Exist\n" +
                "Roulet job 6 Doesn't Exist\n" +
                "Domingues job 8 Doesn't Exist\n" +
                "Hernadez job 5 Doesn't Exist\n" +
                "Schmitt job 13 Doesn't Exist\n" +
                "Tonini job 11 Doesn't Exist\n" +
                "Roel job 6 Exists\n" +//Because job 6 was already inserted on row 3, it exists here
                "Lincoln job 14 Doesn't Exist\n" +
                "Chang job 4 Doesn't Exist\n" +
                "Thomas job 9 Doesn't Exist\n" +
                "Nagy job 7 Doesn't Exist\n" +
                "Snyder job 12 Doesn't Exist\n" +
                "Bennett job 12 Exists\n" +//Was added on the previous row
                "Labrune job 5 Exists\n"//was added on the 5th row
            );
        }
        [Test]
        public void Join()
        {
            var employees = new Pubs.Employees();
            var jobs = new Pubs.Jobs();
            employees.InitializeWithTestData();
            jobs.InitializeWithTestData();
            DeleteJobBusinessOperationsManager();

            var bp = new BusinessProcess
            {
                From = employees
            };
            bp.OrderBy.Segments.Add(employees.Id);
            bp.Relations.Add(jobs, RelationType.Join,
                jobs.Id.IsEqualTo(employees.JobId));
            string namesAndJobs = "";
            bp.ForEachRow(() =>
            {
                namesAndJobs += employees.LastName.Value.TrimEnd() + " - " +
                                jobs.Description.Value.TrimEnd() + "\n";
                if (bp.Counter == 5)
                    bp.Exit();
            });
            namesAndJobs.ShouldBe("Cruz - Productions Manager\n" +
                "Roulet - Managing Editor\n" +//Devon was not written as his job (5) was deleted
                "Domingues - Public Relations Manager\n" +
                "Hernadez - Publisher\n"+
                "Schmitt - Sales Representative\n");
        }
        [Test]
        public void OuterJoin()
        {
            var employees = new Pubs.Employees();
            var jobs = new Pubs.Jobs();
            employees.InitializeWithTestData();
            jobs.InitializeWithTestData();
            DeleteJobBusinessOperationsManager();

            var bp = new BusinessProcess
            {
                From = employees
            };
            bp.OrderBy.Segments.Add(employees.Id);
            bp.Relations.Add(jobs, RelationType.OuterJoin,
                jobs.Id.IsEqualTo(employees.JobId));
            string namesAndJobs = "";
            bp.ForEachRow(() =>
            {
                namesAndJobs += employees.LastName.Value.TrimEnd() + " - " +
                                jobs.Description.Value.TrimEnd() + "\n";
                if (bp.Counter == 5)
                    bp.Exit();
            });
            namesAndJobs.ShouldBe("Cruz - Productions Manager\n" +
                "Roulet - Managing Editor\n" +
                "Devon - \n" +
                "Domingues - Public Relations Manager\n" +
                "Hernadez - Publisher\n");
        }
        void DeleteJobBusinessOperationsManager()
        {
            var jobs = new Pubs.Jobs();
            var bp = new BusinessProcess()
                         {
                             From = jobs,
                             Activity = Activities.Delete
                         };
            bp.Where.Add(jobs.Id.IsEqualTo(3));
            bp.Run();
        }
    }
    }

Examples

reevaluation of relations
This example is in the form of Unit Tests. It references the NUnit framework. This framework can be downloaded from www.NUnit.org. For more information about unit testing visit: www.NUnit.org.
This example is based on test data. The code for the entities included in this test data can be found in the documentation of Entity
CopyC#
using System;
using System.Collections.Generic;
using System.Text;
using Firefly.Box.Data;
using NUnit.Framework;
using Firefly.Box;
using Firefly.Box.Testing;

namespace TestFirefly.Box.Documentation
{
    [TestFixture]
    public class ReevaluationOfRelations
    {
        [Test]
        public void RelationReevaluation()
        {
            var jobs = new Pubs.Jobs();
            jobs.InitializeWithTestData();

            var bp = new BusinessProcess();
            var selectedJobId = new NumberColumn
            {
                DefaultValue = 1
            };
            bp.Relations.Add(jobs, jobs.Id.IsEqualTo(selectedJobId));
            bp.Columns.Add(selectedJobId);

            bp.Columns.Add(jobs.Id, jobs.Description);//The relation columns are selected after the column that
            // the relation is based on
            bp.ForFirstRow(() =>
            {
                selectedJobId.ShouldBe(1);//The default value
                jobs.Description.ShouldBe("New Hire - Job not specified");//The job with id = 1
                selectedJobId.Value = 5;
                jobs.Description.ShouldBe("Publisher");//The relation reevaluated and fetched 
                //the row with id = 5 - the publisher row
            });
        }
        [Test]
        public void RelationReevaluationCommonError()
        {
            var jobs = new Pubs.Jobs();
            jobs.InitializeWithTestData();

            var bp = new BusinessProcess();
            var selectedJobId = new NumberColumn
            {
                DefaultValue = 1
            };
            bp.Relations.Add(jobs, jobs.Id.IsEqualTo(selectedJobId));

            bp.Columns.Add(jobs.Id, jobs.Description);// The common error is that the relation columns
            //were selected before the column that the relation is based on (SelectedJobId) 
            //thus the relation will be evaluated when the row is entered, but not evaluated when
            //the value of SelectedJobId is changed
            bp.Columns.Add(selectedJobId);


            bp.ForFirstRow(() =>
            {
                selectedJobId.ShouldBe(1);//The default value
                jobs.Description.ShouldBe("New Hire - Job not specified");//The job with id = 1
                selectedJobId.Value = 5;
                selectedJobId.ShouldBe(5);
                jobs.Description.ShouldBe("New Hire - Job not specified");//The relation did not reevaluate
            });
        }
    }
}

See Also