IEnumerable<Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>> GetNamedStreamTests()
        {
            // attach and save named stream, expect failure
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                PeopleManager andy = new PeopleManager { ID = 2 };
                ctx.AttachTo("People", andy);
                ctx.SetSaveStream(andy, "Photo", new MemoryStream(), true, "abc/pqr");
                ctx.SaveChanges(saveChangeOption);
            },
            new List<Version>() { V4 },
            "The stream named 'Photo' cannot be modified because it does not have an edit-media link. Make sure that the stream name is correct and that an edit-media link for this stream is included in the entry element in the response.");

            // attach and load named stream, expect failure
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                PeopleManager andy = new PeopleManager { ID = 2 };
                ctx.AttachTo("People", andy);
                ctx.GetReadStream(andy, "Photo", new DataServiceRequestArgs());
                ctx.SaveChanges(saveChangeOption);
            },
            new List<Version>() { V4 },
            "The entity does not have a stream named 'Photo'. Make sure that the name of the stream is correct.\r\nParameter name: name");

            // retrive entity and save/load named stream
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 3);
                Employee pratik = (Employee)query.Single();
                ctx.SetSaveStream(pratik, "Photo", new MemoryStream(new byte[] { 1,2,3}), true, "abc/pqr");
                ctx.SaveChanges(saveChangeOption);
                
                DataServiceRequestArgs arg = new DataServiceRequestArgs() { AcceptContentType = "abc/pqr" };
                var response = ctx.GetReadStream(pratik, "Photo", new DataServiceRequestArgs() { AcceptContentType = "abc/pqr" });
                byte[] buffer = new byte[4];
                Assert.AreEqual(3, response.Stream.Read(buffer, 0, 4));
                Assert.IsTrue(buffer[0] == 1 && buffer[1] == 2 && buffer[2] == 3);
            },
            new List<Version>() { V4, V4, V4 },
            null);
        }
        IEnumerable<Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>> GetSetLinkTests()
        {
            // set link to attached objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                Employee pratik = new Employee { ID = 3 };
                Employee marcelo = new Employee { ID = 6 };
                ctx.AttachTo("People", pratik);
                ctx.AttachTo("People", marcelo);
                ctx.SetLink(pratik, "BestFriend", marcelo);

                ctx.SaveChanges(saveChangeOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => p.BestFriend).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(person, pratik);
                Assert.AreEqual(6, marcelo.ID);
                Assert.AreEqual(marcelo, pratik.BestFriend);

                Assert.AreEqual(pratik, (Person)ctx.Links.Single().Source);
                Assert.AreEqual(marcelo, (Person)ctx.Links.Single().Target);
            },
            new List<Version>() { V4, V4 },
            null);

            // set link to retrieved objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 3);
                Employee pratik = (Employee)query.Single();
                Employee marcelo = new Employee { ID = 6 };
                ctx.AttachTo("People", marcelo);
                ctx.SetLink(pratik, "BestFriend", marcelo);

                ctx.SaveChanges(saveChangeOption);

                query = ctx.CreateQuery<Person>("People").Expand(p => p.BestFriend).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(pratik, person);
                Assert.AreEqual(6, marcelo.ID);
                Assert.AreEqual(marcelo, pratik.BestFriend);

                Assert.AreEqual(pratik, (Person)ctx.Links.Single().Source);
                Assert.AreEqual(marcelo, (Person)ctx.Links.Single().Target);
            },
            new List<Version>() { V4, V4, V4 },
            null);

            // set link to newly added objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Person p100 = new Person { ID = 100 };
                Person p101 = new Person { ID = 101 };
                ctx.AddObject("People", p100);
                ctx.AddObject("People", p101);
                ctx.SetLink(p100, "BestFriend", p101);

                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => p.BestFriend).Where(p => p.ID == 100);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(100, person.ID);
                Assert.AreEqual(p100, person);
                Assert.AreEqual(101, p101.ID);
                Assert.AreEqual(p101, p100.BestFriend);

                Assert.AreEqual(p100, (Person)ctx.Links.Single().Source);
                Assert.AreEqual(p101, (Person)ctx.Links.Single().Target);
            },
            new List<Version>() { V4, V4, V4, V4 },
            null);

            // set link to existing objects, for derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Employee pratik = null;
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 3);
                foreach (Person p in query)
                {
                    pratik = (Employee)p;
                    Assert.IsTrue(ctx.GetEntityDescriptor(p).EditLink.OriginalString.EndsWith(typeof(Employee).FullName), "href for edit link did not end with type name");
                }

                PeopleManager shyam = new PeopleManager { ID = 5 };
                ctx.AttachTo("People", shyam);
                ctx.SetLink(pratik, "Manager", shyam);

                ctx.SaveChanges(saveChangesOption);

                query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Manager).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(pratik, person);
                Assert.AreEqual(5, shyam.ID);
                Assert.AreEqual(shyam, pratik.Manager);

                Assert.AreEqual(pratik, ctx.Links.Single().Source);
                Assert.AreEqual(shyam, ctx.Links.Single().Target);
            },
            new List<Version>() { V4, V4, V4 },
            null);

            // set link to existing objects, for derived property, should fail for attach
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Employee pratik = new Employee { ID = 3 };
                PeopleManager shyam = new PeopleManager { ID = 5 };
                ctx.AttachTo("People", pratik);
                ctx.AttachTo("People", shyam);
                ctx.SetLink(pratik, "Manager", shyam);

                try
                {
                    ctx.SaveChanges(saveChangesOption);
                    Assert.Fail("Exception expected but received none.");
                }
                catch (DataServiceRequestException e)
                {
                    t.TestUtil.AssertContains(e.InnerException.Message, "Resource not found for the segment 'Manager'.");
                }
            },
            new List<Version>() { V4 },
            null);

            // set link to null, for derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Employee pratik = null;
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 3);
                foreach (Person p in query)
                {
                    pratik = (Employee)p;
                    Assert.IsTrue(ctx.GetEntityDescriptor(p).EditLink.OriginalString.EndsWith(typeof(Employee).FullName), "href for edit link did not end with type name");
                }

                ctx.SetLink(pratik, "Manager", null);
                ctx.SaveChanges(saveChangesOption);

                query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Manager).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(pratik, person);
                Assert.IsNull(pratik.Manager);

                Assert.AreEqual(pratik, ctx.Links.Single().Source);
                Assert.IsNull(ctx.Links.Single().Target);
            },
            new List<Version>() { V4, V4, V4 },
            null);

            // set link to newly added objects, for derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Employee p100 = new Employee { ID = 100 };
                p100.Skills = new List<string>();
                p100.Vacations = new List<Vacation>();

                PeopleManager p101 = new PeopleManager { ID = 101 };
                p101.Skills = new List<string>();
                p101.Vacations = new List<Vacation>();

                ctx.AddObject("People", p100);
                ctx.AddObject("People", p101);
                ctx.SetLink(p100, "Manager", p101);

                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Manager).Where(p => p.ID == 100);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(100, person.ID);
                Assert.AreEqual(p100, person);
                Assert.AreEqual(101, p101.ID);
                Assert.AreEqual(p101, p100.Manager);

                Assert.AreEqual(p100, ctx.Links.Single().Source);
                Assert.AreEqual(p101, ctx.Links.Single().Target);
            },
            new List<Version>() { V4 /*b/c of collection properties*/, V4 /*b/c of collection properties*/, V4, V4 },
            null);

            // set link to newly added objects, for derived property with link folding
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Employee p100 = new Employee { ID = 100 };
                p100.Skills = new List<string>();
                p100.Vacations = new List<Vacation>();

                PeopleManager p101 = new PeopleManager { ID = 101 };
                p101.Skills = new List<string>();
                p101.Vacations = new List<Vacation>();

                ctx.AddObject("People", p101);
                ctx.AddObject("People", p100);
                ctx.SetLink(p100, "Manager", p101);

                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Manager).Where(p => p.ID == 100);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(100, person.ID);
                Assert.AreEqual(p100, person);
                Assert.AreEqual(101, p101.ID);
                Assert.AreEqual(p101, p100.Manager);

                Assert.AreEqual(p100, ctx.Links.Single().Source);
                Assert.AreEqual(p101, ctx.Links.Single().Target);
            },
            new List<Version>() { V4 /*b/c of collection properties*/, V4 /*b/c of collection properties*/, V4 },
            null);
        }
        IEnumerable<Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>> GetDeleteLinkTests()
        {
            // delete link to attached objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                Employee pratik = new Employee { ID = 3 };
                Person p1 = new Person { ID = 1 };
                ctx.AttachTo("People", pratik);
                ctx.AttachTo("People", p1);
                ctx.DeleteLink(pratik, "Friends", p1);

                ctx.SaveChanges(saveChangeOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => p.Friends).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(pratik, person);
                Assert.IsFalse(pratik.Friends.Any());
                Assert.AreEqual(0, ctx.Links.Count());
            },
            new List<Version>() { V4, V4 },
            null);

            // delete link to retrieved objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 3);
                Employee pratik = (Employee)query.Single();
                Person p1 = new Person { ID = 1 };
                ctx.AttachTo("People", p1);
                ctx.DeleteLink(pratik, "Friends", p1);

                ctx.SaveChanges(saveChangeOption);

                query = ctx.CreateQuery<Person>("People").Expand(p => p.Friends).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(pratik, person);
                Assert.IsFalse(pratik.Friends.Any());
                Assert.AreEqual(0, ctx.Links.Count());
            },
            new List<Version>() { V4, V4, V4 },
            null);

            // delete link to retrieved object, for derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Employee marcelo = null;
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 6);
                foreach (Person p in query)
                {
                    marcelo = (Employee)p;
                    Assert.IsTrue(ctx.GetEntityDescriptor(p).EditLink.OriginalString.EndsWith(typeof(Employee).FullName), "href for edit link did not end with type name");
                }

                PeopleManager andy = new PeopleManager { ID = 2 };
                ctx.AttachTo("People", andy);
                ctx.DeleteLink(marcelo, "Colleagues", andy);

                ctx.SaveChanges(saveChangesOption);

                query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Colleagues).Where(p => p.ID == 6);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(6, person.ID);
                Assert.AreEqual(marcelo, person);
                Assert.IsFalse(marcelo.Colleagues.Any());
                Assert.AreEqual(0, ctx.Links.Count());
            },
            new List<Version>() { V4, V4, V4 },
            null);

            // Delete newly added links, for derived property with link folding
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                ctx.Format.UseJson(this.LoadModelFromString());
                PeopleManager shyam = new PeopleManager { ID = 5 };
                Employee marcelo = new Employee { ID = 6 };

                ctx.AttachTo("People", shyam);
                ctx.AttachTo("People", marcelo);

                ctx.DeleteLink(shyam, "DirectReports", marcelo);
                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => (p as PeopleManager).DirectReports).Where(p => p.ID == 5);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(5, person.ID);
                Assert.AreEqual(shyam, person);
                Assert.AreEqual(6, marcelo.ID);
                Assert.AreEqual(1, ctx.Links.Count());
            },
            new List<Version>() { V4 , V4 },
            null);
        }
        IEnumerable<Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>> GetAddLinkTests()
        {
            // add link to attached objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                Employee pratik = new Employee { ID = 3 };
                Employee marcelo = new Employee { ID = 6 };
                ctx.AttachTo("People", pratik);
                ctx.AttachTo("People", marcelo);
                ctx.AddLink(pratik, "Friends", marcelo);

                ctx.SaveChanges(saveChangeOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => p.Friends).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(pratik, person);
                Assert.AreEqual(6, marcelo.ID);
                Assert.IsNotNull(pratik.Friends.Single(f => f == marcelo));

                Assert.AreEqual(2, ctx.Links.Where(l => l.Source == pratik).Count());
                Assert.IsNotNull(ctx.Links.Single(l => l.Target == marcelo));
            },
            new List<Version>() { V4, V4 },
            null);

            // add link to retrieved objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangeOption) =>
            {
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 3);
                Employee pratik = (Employee)query.Single();
                Employee marcelo = new Employee { ID = 6 };
                ctx.AttachTo("People", marcelo);
                ctx.AddLink(pratik, "Friends", marcelo);

                ctx.SaveChanges(saveChangeOption);

                query = ctx.CreateQuery<Person>("People").Expand(p => p.Friends).Where(p => p.ID == 3);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(3, person.ID);
                Assert.AreEqual(pratik, person);
                Assert.AreEqual(6, marcelo.ID);
                Assert.IsNotNull(pratik.Friends.Single(f => f == marcelo));

                Assert.AreEqual(2, ctx.Links.Where(l => l.Source == pratik).Count());
                Assert.IsNotNull(ctx.Links.Single(l => l.Target == marcelo));
            },
            new List<Version>() { V4, V4, V4 },
            null);

            // add link to newly added objects, for non-derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                Person p100 = new Person { ID = 100 };
                Person p101 = new Person { ID = 101 };
                ctx.AddObject("People", p100);
                ctx.AddObject("People", p101);
                ctx.AddLink(p100, "Friends", p101);

                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => p.Friends).Where(p => p.ID == 100);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(100, person.ID);
                Assert.AreEqual(p100, person);
                Assert.AreEqual(101, p101.ID);
                Assert.AreEqual(p101, p100.Friends.Single());

                Assert.AreEqual(p100, (Person)ctx.Links.Single().Source);
                Assert.AreEqual(p101, (Person)ctx.Links.Single().Target);
            },
            new List<Version>() { V4, V4, V4, V4 },
            null);

            // add link to existing objects, for derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                PeopleManager shyam = null;
                var query = ctx.CreateQuery<Person>("People").Where(p => p.ID == 5);
                foreach (Person p in query)
                {
                    shyam = (PeopleManager)p;
                    Assert.IsTrue(ctx.GetEntityDescriptor(p).EditLink.OriginalString.EndsWith(typeof(PeopleManager).FullName), "href for edit link did not end with type name");
                }

                Employee marcelo = new Employee { ID = 6 };
                ctx.AttachTo("People", marcelo);
                ctx.AddLink(shyam, "Colleagues", marcelo);

                ctx.SaveChanges(saveChangesOption);

                query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Colleagues).Where(p => p.ID == 5);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(5, person.ID);
                Assert.AreEqual(shyam, person);
                Assert.AreEqual(6, marcelo.ID);
                Assert.AreEqual(marcelo, shyam.Colleagues.Single(e => e.ID == 6));

                Assert.IsNotNull(ctx.Links.SingleOrDefault(l => l.SourceProperty == "Colleagues" && l.Source == shyam && l.Target == marcelo));
            },
            new List<Version>() { V4, V4, V4 },
            null);

            // add link to newly added objects, for derived property with link folding
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                ctx.Format.UseJson(this.LoadModelFromString());
                PeopleManager shyam = new PeopleManager { ID = 5 };
                Employee pratik = new Employee { ID = 3 };

                ctx.AttachTo("People", shyam);
                ctx.AttachTo("People", pratik);

                ctx.AddLink(shyam, "DirectReports", pratik);

                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => (p as PeopleManager).DirectReports).Where(p => p.ID == 5);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(shyam.ID, person.ID);
                Assert.AreEqual(shyam, person);
                Assert.AreEqual(3, pratik.ID);
                Assert.AreEqual(pratik, shyam.DirectReports.FirstOrDefault(l => l.ID == 3));

                Assert.IsNotNull(ctx.Links.SingleOrDefault(l => l.SourceProperty == "DirectReports" && l.Source == shyam && l.Target == pratik));
            },
            new List<Version>() { V4, V4},
            null);

            // add link to newly added objects, for derived property
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                PeopleManager p100 = new PeopleManager { ID = 100 };
                p100.Skills = new List<string>();
                p100.Vacations = new List<Vacation>();

                Employee p101 = new Employee { ID = 101 };
                p101.Skills = new List<string>();
                p101.Vacations = new List<Vacation>();

                ctx.AddObject("People", p100);
                ctx.AddObject("People", p101);
                ctx.AddLink(p100, "Colleagues", p101);

                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Colleagues).Where(p => p.ID == 100);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(100, person.ID);
                Assert.AreEqual(p100, person);
                Assert.AreEqual(101, p101.ID);
                Assert.AreEqual(p101, p100.Colleagues.Single());

                Assert.IsNotNull(ctx.Links.SingleOrDefault(l => l.SourceProperty == "Colleagues" && l.Source == p100 && l.Target == p101));
            },
            new List<Version>() { V4 /*b/c of collection properties*/, V4 /*b/c of collection properties*/, V4, V4 },
            null);

            // add link to newly added objects, for derived property with link folding
            yield return new Tuple<Action<DataServiceContext, SaveChangesOptions>, List<Version>, string>(
            (ctx, saveChangesOption) =>
            {
                PeopleManager p100 = new PeopleManager { ID = 100 };
                p100.Skills = new List<string>();
                p100.Vacations = new List<Vacation>();

                Employee p101 = new Employee { ID = 101 };
                p101.Skills = new List<string>();
                p101.Vacations = new List<Vacation>();

                ctx.AddObject("People", p101);
                ctx.AddObject("People", p100);
                ctx.AddLink(p100, "Colleagues", p101);

                ctx.SaveChanges(saveChangesOption);

                var query = ctx.CreateQuery<Person>("People").Expand(p => (p as Employee).Colleagues).Where(p => p.ID == 100);
                ctx.MergeOption = MergeOption.OverwriteChanges;

                Person person = query.Single();
                Assert.AreEqual(100, person.ID);
                Assert.AreEqual(p100, person);
                Assert.AreEqual(101, p101.ID);
                Assert.AreEqual(p101, p100.Colleagues.Single());

                Assert.IsNotNull(ctx.Links.SingleOrDefault(l => l.SourceProperty == "Colleagues" && l.Source == p100 && l.Target == p101));
            },
            new List<Version>() { V4 /*b/c of collection properties*/, V4 /*b/c of collection properties*/, V4 },
            null);
        }